none
ListView Filtering Function in VB2010

    问题

  • Hi, I am currently making a mini-tool that can check about information of something, like an offline dictionary.

    Now, i am going to make a search box for the items so that users can find the information they want easily.

    *My ListView has Small Icons attached.

    *My ListView has a lot of data.

    ~

    I am currently using this code (I put in my SearchBox.TextChanged)

        Private Sub Filter(ByVal Listview As ListView, ByVal FilterText As String)
            For Each Item As ListViewItem In Listview.Items
                If Not Item.SubItems(0).Text.Contains(FilterText) Then
                    Item.Remove()
                End If
            Next
        End Sub

    But it only removes the unmatched items but not recovering matched-again items.

    Please Help me !

    2012年6月29日 12:36

答案

  • Andy,

    This topic – filtering data that’s in a ListView – has come up several times over the years and I thought I’d take time to write an example program to do just that.

    This is, of course, not the only way to do it – not by a long shot! But it’s one way.

    What I set out to do was to make a program that should work on anyone’s computer, and to that end, it does something rather simple: It asks the user to browse to a folder and select it. Following that, it puts the path and the file name of all files (including subfolders) into a two-column ListView and then offers to filter that data based on any of several ways.

    This is not set up to handle protected paths so do be careful not to select one.

    The form looks like this when first started:

    The code for it is on a page of my website here and if you want, you can download the entire project folder by downloading it here; use that to experiment with if you’d like.

    If you look at the code section for the Filter The List buttons’ click event, you’ll see the heart of it all – it uses LINQ to filter the data. Note also that there’s a class and a ListOf(Class) used here; that’s why it’s so fast to work once the initial file data has been parsed through.

    The results are shown below:

    I hope you or someone else reading this thread might find this helpful.


    Please call me Frank :)

    2012年7月1日 22:41
  • Hi Frank ... "item.subitems(0).text" means "item.text"

    Hi Andy,

    try this

    Private templist As New ListView 'after editing your original listview Private Sub RefreshMyList(Original As ListView, Temp As ListView) Temp.Items.Clear() For Each item As ListViewItem In Original.Items Temp.Items.Add(item.Clone()) Next End Sub

    'Search Code Private Sub Filter(ByVal Original As ListView, ByVal FilterText As String) Original.BeginUpdate() Original.Items.Clear() For Each item As ListViewItem In templist.Items If item.SubItems(0).Text.Contains(FilterText) Then Original.Items.Add(item.Clone()) End If Next Original.EndUpdate() End Sub



    ahmed taha

    2012年7月1日 10:32

全部回复

  • How are you getting the list items in there to begin with?  Is the ListView bound to a data source or are you creating the items manually?

    I ask because you could possibly do the filtering on the data source and then it would naturally add or remove items from the list view by rebinding.  For instance, if you bind to a dataview then you could have the full set of data in a DataTable and set the default view filter string as the text is changing.  The DataView filtering is very fast - faster than your looping logic undoubtedly.

    Something else to consider is that if you have a massive amount of data then constantly rebinding (or looping as you are doing) will begin to cause delays and hangs in the app since the filtering logic is synchronous (it must complete before it processes the next key stroke from the user).  It may not be ideal but you could consider not filtering with every key stroke, rather when the user presses the enter key or when the textbox leave event fires or have a button or some combination of all these.


    Blog: http://codemidden.wordpress.com

    2012年6月29日 14:53
  • On second thought...  I had forgotten that the ListView is more limited in terms of databinding -- you cannot simply bind to it.  However you could replace the items with each change to the filter.  Performance would likely be very ppor though.

    Another option is to have copies of each list view item in a separate collection and then produce a filteredset from this collection using LINQ perhaps. You would then be able to add items back in that fit the filter critera.


    Blog: http://codemidden.wordpress.com

    2012年6月29日 17:36
  • Hi, i am currently adding items to the ListView manually.

    Is there a solution on the manual items?

    Or, is it possible to save my data at another file and load it to the ListView (But My ListView contains image for each item)

    2012年6月30日 6:36
  • Andy,

    Be aware that there is no SubItem(0), it doesn't exist. You can read more here:

    http://msdn.microsoft.com/en-us/library/system.windows.forms.listviewitem.subitems.aspx#Y0


    Please call me Frank :)

    2012年6月30日 13:32
  • But I put SubItem(0), it works fine. (Removes item perfectly)

    But when i Put SubItem(1), ArgumentOutOfRangeException occur.

    And, is there a code to add the items back to the list

    at this place

    Private Sub Filter(ByVal Listview As ListView, ByVal FilterText As String) For Each Item As ListViewItem In Listview.Items If Not Item.SubItems(0).Text.Contains(FilterText) Then Item.Remove()

    'Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< End If Next End Sub


    ??

    2012年7月1日 1:25
  • Hi Frank ... "item.subitems(0).text" means "item.text"

    Hi Andy,

    try this

    Private templist As New ListView 'after editing your original listview Private Sub RefreshMyList(Original As ListView, Temp As ListView) Temp.Items.Clear() For Each item As ListViewItem In Original.Items Temp.Items.Add(item.Clone()) Next End Sub

    'Search Code Private Sub Filter(ByVal Original As ListView, ByVal FilterText As String) Original.BeginUpdate() Original.Items.Clear() For Each item As ListViewItem In templist.Items If item.SubItems(0).Text.Contains(FilterText) Then Original.Items.Add(item.Clone()) End If Next Original.EndUpdate() End Sub



    ahmed taha

    2012年7月1日 10:32
  • @-->Ahmed

    That might explain a few things - wrong use of terms...

    @-->Andy

    How many columns of data are in your listview? If it's not set to Details, temporarily set it to that view type and tell me - is there just one column of data? If so that would explain a lot.


    Please call me Frank :)

    2012年7月1日 15:34
  • Andy,

    This topic – filtering data that’s in a ListView – has come up several times over the years and I thought I’d take time to write an example program to do just that.

    This is, of course, not the only way to do it – not by a long shot! But it’s one way.

    What I set out to do was to make a program that should work on anyone’s computer, and to that end, it does something rather simple: It asks the user to browse to a folder and select it. Following that, it puts the path and the file name of all files (including subfolders) into a two-column ListView and then offers to filter that data based on any of several ways.

    This is not set up to handle protected paths so do be careful not to select one.

    The form looks like this when first started:

    The code for it is on a page of my website here and if you want, you can download the entire project folder by downloading it here; use that to experiment with if you’d like.

    If you look at the code section for the Filter The List buttons’ click event, you’ll see the heart of it all – it uses LINQ to filter the data. Note also that there’s a class and a ListOf(Class) used here; that’s why it’s so fast to work once the initial file data has been parsed through.

    The results are shown below:

    I hope you or someone else reading this thread might find this helpful.


    Please call me Frank :)

    2012年7月1日 22:41