VB.NET列表视图多列筛选器 [英] VB.NET Listview Multiple Column Filter

查看:124
本文介绍了VB.NET列表视图多列筛选器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是开发使用多个文本框进行搜索。我有五列(ArticleNo,说明,PartNum,制造商和成本),每个都会有一个文本框他们。

My goal is to develop a search using multiple textboxes. I have five columns (ArticleNo, Description, PartNum, Manufacturer and Cost) each of which will have a textbox over them.

我跟踪的初始列表项的使用:

I keep track of the original list items using:

Private originalListItems As New List(Of ListViewItem)

这是充满了所有的项目(6000)。

This is filled with all the items (over 6000).

然后我将有五文本已改变事件存在的基础上创建(tbSearchArticleNo,tbSearchDescription,tbSearchPartNum ...等)的五个文本框

Then I will have five "text changed" events occuring based on the five textboxes created (tbSearchArticleNo, tbSearchDescription, tbSearchPartNum ... etc)

Private Sub tbSearchArticleNo_TextChanged(sender As Object, e As System.EventArgs) Handles tbSearchArticleNo.TextChanged
    If tbSearchDesc.Text <> "" Or tbPartNum.Text <> "" Or tbManufacturer.Text <> "" Or tbCost.Text <> "" Then
        SearchCurrentList(lwArticles, tbSearchArticleNo.Text, 0, False)
    Else
        SearchListView(lwArticles, tbSearchArticleNo.Text, 0, False)
    End If
End Sub

下面是我的方法SearchCurrentList:

Here is my method SearchCurrentList:

Private Sub SearchCurrentList(ByVal listview As ListView, ByVal search As String, ByVal colIndex As Integer, ByVal upperCase As Boolean)
    If upperCase Then
        search = search.ToUpper()
    End If

    listview.BeginUpdate()

    'Clear listview
    lwArticles.Items.Clear()

    'Other textbox has information in it, concatenate both results
    For Each item In currentListItems
        Dim itemToUpper = item.SubItems.Item(colIndex).Text
        If upperCase Then
            itemToUpper = item.SubItems.Item(colIndex).Text.ToUpper()
        End If
        If itemToUpper.Contains(search) Then
            lwArticles.Items.Add(item)
        End If
    Next

    'Reupdate the current list of items
    currentListItems.Clear()
    For Each item In lwArticles.Items
        currentListItems.Add(item)
    Next

    listview.EndUpdate()
End Sub

和这里是我的方法SearchListView:

And here is my method SearchListView:

Private Sub SearchListView(ByVal listview As ListView, ByVal search As String, ByVal colIndex As Integer, ByVal upperCase As Boolean)
    'Upper case parameter determines if you're searching a string, if so, it is better to compare everything by uppercase
    If upperCase Then
        search = search.ToUpper()
    End If

    listview.BeginUpdate()

    If search.Trim().Length = 0 Then
        'Clear listview
        listview.Items.Clear()

        'Clear currentListItems
        currentListItems.Clear()

        'If nothing is in the textbox make all items appear
        For Each item In originalListItems
            listview.Items.Add(item)
        Next

    Else
        'Clear listview
        listview.Items.Clear()

        'Clear currentListItems
        currentListItems.Clear()

        'Go through each item in the original list and only add the ones which contain the search text
        For Each item In originalListItems
            Dim currItem = item.SubItems.Item(colIndex).Text
            If upperCase Then
                currItem = currItem.ToUpper()
            End If
            If currItem.Contains(search) Then
                currentListItems.Add(item)
                listview.Items.Add(item)
            End If
        Next
    End If

    listview.EndUpdate()
End Sub

下面是我搜索的例子:

tbSearchArticleNo.Text =33

tbSearchArticleNo.Text = "33"

这将包含33字符串中的每一个articleNo匹配。现在我想添加其他过滤器:

This will match every articleNo that contains "33" in the string. Now I want to add another filter:

tbSearchDescription.Text =混音器

tbSearchDescription.Text = "Mixer"

这应该与说明,包含33的文章编号,一切都还有混音器。等等等等第四。

This should match everything that contains 33 in the article number as well as "mixer" in the description. And so on and so fourth.

实际的过滤器正常工作 - 我唯一的问题是每当我删除的东西,比如混音器(而在articleNo仍然有33),它不会返回包含33的articleNo的结果。 ..相反,它并没有改变我的搜索结果。有可能是通过这个搜索的更好的办法?

The actual filters are working correctly - my only problem is whenever I erase something, such as "Mixer" (while still having "33" in the articleNo) it doesn't return the results of the articleNo containing "33" ... Instead it doesn't change the results of my search. There might be a better way of searching through this?

推荐答案

处理这方面的一个稍微不同的方式是使用LINQ。下面的函数可用于返回枚举提供集仅包括那些适合的过滤项的对象。您可以使用此枚举重新填充您的列表。如果使用originalListItems每次叫用getFilter的时候,你总是有包括考虑在最新的过滤器每一个项目。

A somewhat different way of handling this is to use LINQ. The following function could be used to return an object that enumerates the provided collection including only those items that fit the filter. You could use this enumerator to re-populate your list. If you used originalListItems each time you called GetFilter, you would always have every item included for consideration in the latest filter.

Function GetFilter(source As IEnumerable(Of ListViewItem), articleNo As String, description As String,
                  partNum As String, prop4 As String, prop5 As String) As IQueryable(Of ListViewItem)
  GetFilter = source.AsQueryable

  Dim articleFilter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
     Function(i As ListViewItem) i.SubItems(0).Text.IndexOf(articleNo, StringComparison.InvariantCultureIgnoreCase) >= 0
  Dim descFilter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
     Function(i As ListViewItem) i.SubItems(1).Text.IndexOf(description, StringComparison.InvariantCultureIgnoreCase) >= 0
  Dim partFilter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
     Function(i As ListViewItem) i.SubItems(2).Text.IndexOf(partNum, StringComparison.InvariantCultureIgnoreCase) >= 0
  Dim prop4Filter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
     Function(i As ListViewItem) i.SubItems(3).Text.IndexOf(prop4, StringComparison.InvariantCultureIgnoreCase) >= 0
  Dim prop5Filter As Expressions.Expression(Of Func(Of ListViewItem, Boolean)) = _
     Function(i As ListViewItem) i.SubItems(4).Text.IndexOf(prop5, StringComparison.InvariantCultureIgnoreCase) >= 0

  If Not String.IsNullOrEmpty(articleNo) Then GetFilter = Queryable.Where(GetFilter, articleFilter)
  If Not String.IsNullOrEmpty(description) Then GetFilter = Queryable.Where(GetFilter, descFilter)
  If Not String.IsNullOrEmpty(partNum) Then GetFilter = Queryable.Where(GetFilter, partFilter)
  If Not String.IsNullOrEmpty(prop4) Then GetFilter = Queryable.Where(GetFilter, prop4Filter)
  If Not String.IsNullOrEmpty(prop5) Then GetFilter = Queryable.Where(GetFilter, prop5Filter)
End Function

较好,多一点思考,你很可能使articleNo和其他参数与更大范围内的变量,并调整函数嵌入IsNullOrEmpty检查进可查询前pression,然后你不会告发'吨需要甚至重新生成过滤器时,字段值的变化。你可以在变量只是设置为新文本框的值,并重新评估已经生成的过滤器前pression,将考虑在变量的新值从而产生新的筛选结果。

Better yet, with a little more thought, you could probably make articleNo and the other parameters into variables with a larger scope, and adjust the function to embed IsNullOrEmpty checking into the Queryable expression, and then you wouldn't need to even re-generate the filter when a field value changes. You could just set the variable to the new textbox value and re-evaluate the already-generated filter expression, which will consider the new values in the variables thus yielding newly filtered results.

下面就是我希望它被使用:

Here's how I would expect it to be used:

lwArticles.Items.Clear()
For Each i In GetFilter(originalListItems, tbSearchArticleNo.Text, tbSearchDesc.Text, tbPartNum.Text, tbManufacturer.Text, tbCost.Text)
   lwArticles.Items.Add(i)
Next

这篇关于VB.NET列表视图多列筛选器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆