Meilleur auteur de réponses
Utilisation de predicate pour rechercher un élément de ma listview et/ou filtrer ces éléments.

Question
-
Bonjour, je me permet de revenir vers vous pour un autre problème :
Je remplis ma listview avec des éléments de ma base de données, dont voici le code :
Imports System.Collections.ObjectModel Class MainWindow Private db As New OMSContext Private CustomerData As New ObservableCollection(Of Customer) Private View As ListCollectionView Dim LastSearchString As String = String.Empty Dim LastFoundIndex As Integer = 0 Public Property Customer() As ObservableCollection(Of Customer) Get Return CustomerData End Get Set(ByVal value As ObservableCollection(Of Customer)) CustomerData = value End Set End Property Private Sub Window1_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded Dim Result = From c In db.Customers _ Select c Me.CustomerData = New CustomerCollection(Result, db) Dim customerSource = CType(Me.Resources("CustomerSource"), CollectionViewSource) customerSource.Source = Me.CustomerData Me.View = CType(customerSource.View, ListCollectionView) End Sub Private Sub btnDelete_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnDelete.Click CustomerData.Remove(lbContacts.SelectedItem) db.SaveChanges() End Sub Private Sub btnAdd_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnAdd.Click Dim window As New Window1 If window.ShowDialog = True Then If window.lbContacts IsNot Nothing Then Customer.Add(window.customer) End If End If 'Dim w As New Window1() 'w.Show() End Sub Private Sub btnSearch_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSearch.Click Dim i As Integer lbContacts.SelectedItems.Clear() For i = 0 To lbContacts.Items.Count - 1 If lbContacts.Items(i).ToString().Contains(TextBox1.Text) Then lbContacts.Items(i).Selected = True End If Next End Sub End Class
Ce que j'essai de faire sur l'évènement "btnSearch_Click", c'est de comparer un à un les éléments de ma listView avec le contenu de ma textbox, et enfin de selectionner cet élément, une fois trouvé. mais Sans succès.
Une autre solution, serait qu'a chaque caractère entré dans la textbox, la listView serait filtrer, jusqu'au terme recherché (qui serait par la même occasion selectionné), mais également sans succès.
La solution d'utiliser des prédicats ou délégués me paraissent un peux flous.
Si quelqu'un pouvait m'éclairé, sur ma problèmatique, ce serait très gentil.
Merci d'avance.
Cordialement.
Réponses
-
Je vous remercie beaucoup pour toute l'aide que vous m'avez apporté.
Voici la solution à mon problème, qui est résolu grâce à votre aide :
Private Sub btnSearch_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSearch.Click Dim i As Integer lbContacts.SelectedItems.Clear() For i = 0 To lbContacts.Items.Count - 1 If CType(lbContacts.Items(i), Customer).FirstName.Contains(TxtSearch.Text) Then lbContacts.SelectedItems.Add(lbContacts.Items(i)) MsgBox(lbContacts.Items(i).FirstName & Chr(10) & lbContacts.Items(i).LastName) End If Next End Sub
L'objectif de petit code est de chercher un élément dans une ListView, de selectionner cet élément, et de l'afficher dans une popup.
Merci encore et à très bientôt.
Cordialement.
- Marqué comme réponse Kensi22 mercredi 5 décembre 2012 18:02
-
Bonjour les amis, voici une autre solution pour effectuer une recherche au sein d'une listview (par filtrage):
tout d'abord la classe
Public Class SampleClass Private _name As String Private _show As Boolean Public Sub New(ByVal name As String, ByVal show As Boolean) _name = name _show = show End Sub Public Property Name() As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property Public Property Show() As Boolean Get Return _show End Get Set(ByVal value As Boolean) _show = value End Set End Property End Class
Ensuite le formulaire XAML
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Search!" Width="200" Height="500" FontSize="13" WindowStartupLocation="CenterScreen"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <DockPanel Grid.Row="0" Margin="2"> <TextBlock Margin="0,0,4,0" Text="Search for:" VerticalAlignment="Center" /> <TextBox x:Name="txtSearch" /> </DockPanel> <ListView Grid.Row="1" Name="myListView"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </Window>
Le code behind
Imports System.ComponentModel Imports System.Collections.ObjectModel Class MainWindow Dim view As ICollectionView Dim collection As ObservableCollection(Of SampleClass) = New ObservableCollection(Of SampleClass) Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded collection.Add(New SampleClass("Abraham", True)) collection.Add(New SampleClass("Banker", False)) collection.Add(New SampleClass("Cartman", True)) collection.Add(New SampleClass("Doctor", True)) collection.Add(New SampleClass("Edwin", False)) collection.Add(New SampleClass("Furniture", True)) collection.Add(New SampleClass("Gopher", True)) collection.Add(New SampleClass("Hyman", False)) collection.Add(New SampleClass("Isabella", False)) collection.Add(New SampleClass("Jerkinheimer", False)) collection.Add(New SampleClass("Karma", True)) collection.Add(New SampleClass("Llamamama", True)) collection.Add(New SampleClass("Martini", True)) collection.Add(New SampleClass("Nachowinkeltoes", True)) collection.Add(New SampleClass("Oreos", False)) collection.Add(New SampleClass("Pillowfighter", False)) collection.Add(New SampleClass("Quintessence", False)) collection.Add(New SampleClass("Razzamatazz", True)) collection.Add(New SampleClass("Shovel", True)) collection.Add(New SampleClass("Towel", False)) collection.Add(New SampleClass("Ultraviolet", False)) collection.Add(New SampleClass("Viagraholic", False)) collection.Add(New SampleClass("VValeri", False)) collection.Add(New SampleClass("Mohamed", False)) collection.Add(New SampleClass("Karim", False)) collection.Add(New SampleClass("Morad", False)) collection.Add(New SampleClass("Whappolongolicitis", False)) collection.Add(New SampleClass("Xylophonic", True)) collection.Add(New SampleClass("Yistlelotusmoustahoppenfield", True)) collection.Add(New SampleClass("Zoraxboraxjajaja", True)) myListView.ItemsSource = collection view = CollectionViewSource.GetDefaultView(collection) AddHandler txtSearch.TextChanged, AddressOf txtSearch_TextChanged End Sub Private Function FilterItems(ByVal param As SampleClass) As Boolean If txtSearch.Text = "" Then Return True End If myListView.SelectedItems.Add(myListView.Items(0)) Return param.Name.StartsWith(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase) End Function Private Sub txtSearch_TextChanged(sender As System.Object, e As System.Windows.Controls.TextChangedEventArgs) Handles txtSearch.TextChanged Dim FilterText As String = txtSearch.Text If [String].IsNullOrEmpty(FilterText) Then view.Filter = Nothing Else view.Filter = New Predicate(Of Object)(AddressOf FilterItems) End If End Sub End Class
En fait ce petit programme filtre les données contenues dans la listview, au fur et à mesure que l'on entre le terme à rechercher dans la textbox. Le premier termes est toujours sélectionné.
Merci à tous.
Cordialement
- Marqué comme réponse Kensi22 vendredi 14 décembre 2012 17:44
Toutes les réponses
-
Bonjour,
Avez-vous vérifier ce que retourne lbContacts.Items(i).ToString() ?
Je pense que vous allez voir que lbContacts.Item(i) retourne en fait un objet dont ToString sort le type. Et donc à priori, il faudrait faire qq chose comme if CType(lbContact.Items(i),CustomerData).Nom.Contains(TextBox1.Text) etc...
Je cherche à trouver la source du problème dans un premier temps en gardant votre méthode actuelle...
Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
-
Bonjour,
Est-ce que vous avez testé les solutions proposées ? Merci de partager avec nous les résultats, afin que d'autres personnes avec le même problème puissent profiter de cette solution.
Cordialement,
Aurel
-
Bonjour, j'ai bien testé la solution proposée par M. Scribe. Bien sûr celle-ci fonctionne parfaitement, mais ne résoud pas mon problème.
En effet :
Private Sub btnSearch_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSearch.Click Dim i As Integer lbContacts.SelectedItems.Clear() For i = 0 To lbContacts.Items.Count - 1 If CType(lbContacts.Items(i), Customer).FirstName.Contains(TextBox1.Text) Then lbContacts.Items(i).Selected = True MsgBox(lbContacts.SelectedItems.ToString) End If Next End Sub
La comparaison entre le contenu de la textbox et celui de la listview a bien lieu. Chaque élément de la listview est comparé à celui de la textbox. Dès que la condition est remplie, l'élément en question doit être sélectionné (lbContacts.Items(i).Selected = True). Mais cela ne fonctionne pas. Voici le message :
"L'exception System.MissingMemberException n'a pas été gérée
Message=Le membre public 'Selected' du type 'Customer_6A2DA7E572980632CA0D5FE0CBF33AEC625A9C4A0E51E42970076151414DB99A' est introuvable."Pour ce qui est du message de test ("MsgBox(lbContacts.SelectedItems.ToString)"), je ne sais pas s'il fonctionne.
Je vous remercie d'avance de votre aide.
Cordialement
-
Ah oui, j'avais zappé le problème suivant sur lbContacts(i).Selected=true... Pour sélectionner un élement, essayez plutôt lbContacts.SelectedItems.Add(lbContacts.Items(i)).
Le principe est que la liste Items est la liste de tous les clients à afficher et de même SelectedItems est la liste de tous les clients actuellement sélectionnés. Donc on va juste ajouter dans cette dernière liste, les clients voulus (d'où le SelectedItems.Add). Actuellement on essaie de modifier la propriété Selected d'un client mais cette propriét n'existe pas (et même si c'était le cas, ce serait juste un booléen attaché à chaque client et qui n'aurait aucun sens particulier pour le contrôle qui se contente de voir si l'objet est ou non dans la liste SelectedItems des objets sélectionnés).
Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
- Modifié Patrice ScribeMVP mardi 4 décembre 2012 18:51
-
Bonjour, je vous remercie beaucoup de votre réactivité, et cela correspond parfaitement à mes attentes.
Un dernier petit hic survient, c'est l'affichage de l'élément selectionné.
En effet :
Private Sub btnSearch_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSearch.Click Dim i As Integer lbContacts.SelectedItems.Clear() For i = 0 To lbContacts.Items.Count - 1 If CType(lbContacts.Items(i), Customer).FirstName.Contains(TextBox1.Text) Then lbContacts.SelectedItems.Add(lbContacts.Items(i)) MsgBox(lbContacts.SelectedItems.ToString) End If Next End Sub
La comparaison entre le contenu de la textbox et celui de la listview a bien lieu. Chaque élément de la listview est comparé à celui de la textbox. Dès que la condition est remplie, l'élément en question est sélectionné ("lbContacts.SelectedItems.Add(lbContacts.Items(i))").
Pour ce qui est du message de test ("MsgBox(lbContacts.SelectedItems.ToString)"), il devrait m'afficher l'élément sélectionné, mais au lieu de ceci, il m'affiche : "System.Windows.Controls.SelectedItemCollection".
Je vous remercie d'avance de votre aide.
Cordialement
-
Non, c'est normal. Il s'agit d'une liste d'éléments qui peut parfaitement contenir plusieurs éléments. De plus ces éléments peuvent être de n'importe quel type et il est impossible à ce contrôle d'afficher une répresentation de cette collection qui serait comme par hasard sous la forme voulue.
Par défaut ToString retourne le nom complet de son type ce qui est donc le résultat que vous avez.
Si vous voulez afficher le client que vous venez d'ajouter lbContacts(i).Nom par exemple (ou la propriété la plus significative pour vous).
lbContacts(i).ToString donnera encore par défaut le nom complet de la classe. Mais vous pouvez éventuellement définir le ToString de la classe client de façon à retourner les infos les plus significatives pour vous comme peut-être le nom et le prénom etc...
Voir http://msdn.microsoft.com/fr-fr/library/system.object.tostring.aspx
Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".
-
Je vous remercie beaucoup pour toute l'aide que vous m'avez apporté.
Voici la solution à mon problème, qui est résolu grâce à votre aide :
Private Sub btnSearch_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSearch.Click Dim i As Integer lbContacts.SelectedItems.Clear() For i = 0 To lbContacts.Items.Count - 1 If CType(lbContacts.Items(i), Customer).FirstName.Contains(TxtSearch.Text) Then lbContacts.SelectedItems.Add(lbContacts.Items(i)) MsgBox(lbContacts.Items(i).FirstName & Chr(10) & lbContacts.Items(i).LastName) End If Next End Sub
L'objectif de petit code est de chercher un élément dans une ListView, de selectionner cet élément, et de l'afficher dans une popup.
Merci encore et à très bientôt.
Cordialement.
- Marqué comme réponse Kensi22 mercredi 5 décembre 2012 18:02
-
Bonjour les amis, voici une autre solution pour effectuer une recherche au sein d'une listview (par filtrage):
tout d'abord la classe
Public Class SampleClass Private _name As String Private _show As Boolean Public Sub New(ByVal name As String, ByVal show As Boolean) _name = name _show = show End Sub Public Property Name() As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property Public Property Show() As Boolean Get Return _show End Get Set(ByVal value As Boolean) _show = value End Set End Property End Class
Ensuite le formulaire XAML
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Search!" Width="200" Height="500" FontSize="13" WindowStartupLocation="CenterScreen"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <DockPanel Grid.Row="0" Margin="2"> <TextBlock Margin="0,0,4,0" Text="Search for:" VerticalAlignment="Center" /> <TextBox x:Name="txtSearch" /> </DockPanel> <ListView Grid.Row="1" Name="myListView"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </Window>
Le code behind
Imports System.ComponentModel Imports System.Collections.ObjectModel Class MainWindow Dim view As ICollectionView Dim collection As ObservableCollection(Of SampleClass) = New ObservableCollection(Of SampleClass) Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded collection.Add(New SampleClass("Abraham", True)) collection.Add(New SampleClass("Banker", False)) collection.Add(New SampleClass("Cartman", True)) collection.Add(New SampleClass("Doctor", True)) collection.Add(New SampleClass("Edwin", False)) collection.Add(New SampleClass("Furniture", True)) collection.Add(New SampleClass("Gopher", True)) collection.Add(New SampleClass("Hyman", False)) collection.Add(New SampleClass("Isabella", False)) collection.Add(New SampleClass("Jerkinheimer", False)) collection.Add(New SampleClass("Karma", True)) collection.Add(New SampleClass("Llamamama", True)) collection.Add(New SampleClass("Martini", True)) collection.Add(New SampleClass("Nachowinkeltoes", True)) collection.Add(New SampleClass("Oreos", False)) collection.Add(New SampleClass("Pillowfighter", False)) collection.Add(New SampleClass("Quintessence", False)) collection.Add(New SampleClass("Razzamatazz", True)) collection.Add(New SampleClass("Shovel", True)) collection.Add(New SampleClass("Towel", False)) collection.Add(New SampleClass("Ultraviolet", False)) collection.Add(New SampleClass("Viagraholic", False)) collection.Add(New SampleClass("VValeri", False)) collection.Add(New SampleClass("Mohamed", False)) collection.Add(New SampleClass("Karim", False)) collection.Add(New SampleClass("Morad", False)) collection.Add(New SampleClass("Whappolongolicitis", False)) collection.Add(New SampleClass("Xylophonic", True)) collection.Add(New SampleClass("Yistlelotusmoustahoppenfield", True)) collection.Add(New SampleClass("Zoraxboraxjajaja", True)) myListView.ItemsSource = collection view = CollectionViewSource.GetDefaultView(collection) AddHandler txtSearch.TextChanged, AddressOf txtSearch_TextChanged End Sub Private Function FilterItems(ByVal param As SampleClass) As Boolean If txtSearch.Text = "" Then Return True End If myListView.SelectedItems.Add(myListView.Items(0)) Return param.Name.StartsWith(txtSearch.Text, StringComparison.InvariantCultureIgnoreCase) End Function Private Sub txtSearch_TextChanged(sender As System.Object, e As System.Windows.Controls.TextChangedEventArgs) Handles txtSearch.TextChanged Dim FilterText As String = txtSearch.Text If [String].IsNullOrEmpty(FilterText) Then view.Filter = Nothing Else view.Filter = New Predicate(Of Object)(AddressOf FilterItems) End If End Sub End Class
En fait ce petit programme filtre les données contenues dans la listview, au fur et à mesure que l'on entre le terme à rechercher dans la textbox. Le premier termes est toujours sélectionné.
Merci à tous.
Cordialement
- Marqué comme réponse Kensi22 vendredi 14 décembre 2012 17:44