none
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.

    mercredi 28 novembre 2012 19:10

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
    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
    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".

    jeudi 29 novembre 2012 12:47
  • 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


    Aurel BERA, Microsoft
    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

    lundi 3 décembre 2012 14:20
    Propriétaire
  • 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

    mardi 4 décembre 2012 18:32
  • 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".


    mardi 4 décembre 2012 18:48
  • 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


    mardi 4 décembre 2012 20:06
  • 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".

    mercredi 5 décembre 2012 09:00
  • 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
    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
    vendredi 14 décembre 2012 17:44