Search code examples
c#.netvb.netwinformsobjectlistview

How to filter on multiple SubItems in ObjectListView


So, I am trying to programmatically add in a ModelFilter to my ObjectListView that will look at two (or more) columns and filters on each separately. Currently, I think that ObjectListView only supports one filter, but I may be missing something in the code/documentation.

As an example, one of my intended filters is to look at column "Active" and that has values of "A" or "T". Another column is a Supervisor Name. So, I want to find all entries where Supervisor name = "Smith" and Active = "A".

I can get the filter to work for either of these options separately using TextMatchFilter, but cannot figure out how to get both to work at the same time.

The minor problem I see is that if the Supervisor Name contains an "A", then using the standard Filter will return the whole row. I have been able to get around that by programmatically setting the Searchable property for columns to false if I don't want to look at them, and then turn them back on once the list is filtered. However, I have a feeling that if I turn Searchable on for the Supervisor column, I will get the unwanted results.

Does anyone know of a way to get the filter to work on multiple columns, using only the indicated columns for each filter?

(I have no sample code to show that helps in solving this. However, if you really want to see what I have for my filtering code, I will be happy to add that; it is in VB however).

Current Code - This looks at a value chosen by the user (searchMeth) and enables searching on that column. It then does the search for what was entered in the txtSearch box. However, in addition to this, I want to add in an additional filter for Supervisor. (See the AndAlso comment

    olvEmps.UseFiltering = True
    OlvColumn1.Searchable = False
    OlvColumn2.Searchable = False
    OlvColumn4.Searchable = False
    OlvColumn3.Searchable = False
    OlvColumn5.Searchable = False

    Select Case searchMeth
        Case "Name"
            OlvColumn1.Searchable = True
        Case "Employee Number"
            OlvColumn2.Searchable = True
        Case "Department"
            OlvColumn3.Searchable = True
    End Select

    olvEmps.OwnerDraw = True
    Dim tFilter As BrightIdeasSoftware.TextMatchFilter = BrightIdeasSoftware.TextMatchFilter.Contains(olvEmps, txtSearch.Text)
    'andalso olvColumn5 = supeName?

    olvEmps.ModelFilter = tFilter
    olvEmps.DefaultRenderer = New BrightIdeasSoftware.HighlightTextRenderer(tFilter)

    OlvColumn1.Searchable = True
    OlvColumn2.Searchable = True
    OlvColumn3.Searchable = True
    OlvColumn4.Searchable = True
    OlvColumn5.Searchable = True

Solution

  • I'm sure the PredicateBuilder solution will work, but ObjectListView comes with a simpler solution already.

    TextMatchFilter can be limited to which columns it searches via the Columns property. Set this to an array of columns that you want to consider.

    TextMatchFilter filter1 = TextMatchFilter.Contains(olvEmps, txtSearch.Text)
    filter1.Columns = new [] { this.olvColumn1, this.olvColumn2 };
    

    You can combine two filters using the CompositeAllFilter to match two or more other filters.

    this.olvEmps.ModelFilter = new CompositeAllFilter(new List<IModelFilter> { filter1, filter2 });