Search code examples
c#objectlistview

Object List View Highlight Renderer with Composite Filters


I'm trying to filter an object list view with a composite filter (i.e. multiple filter conditions) but the default highlight text renderer only renders the text of the first filter.

Is there a way to make it apply to all filters or better yet use multiple text renderers one for each filter?

I'm using control characters (&& and ||) to delimit search terms

Some C&P code to illustrate

public void Filter (string txt, MatchKind matchKind) {
     bool filterByAll;
     IEnumerable<string> terms = SplitSearchTerms(txt, out filterByAll);
     List<IModelFilter> modelFilters = new List<IModelFilter>();
     foreach (string term in terms) {
        IModelFilter filter;
        switch (matchKind) {
              case MatchKind.Contains:
              default:
                 filter = TextMatchFilter.Contains(_olv, term);
                 break;
              case MatchKind.Prefix:
                 filter = TextMatchFilter.Prefix(_olv, term);
                 break;
              case MatchKind.Regex:
                 filter = TextMatchFilter.Regex(_olv, term);
                 break;
           }
        modelFilters.Add(filter);
     }

     CompositeFilter compositeFilter;
     if (filterByAll) {
        compositeFilter = new CompositeAllFilter(modelFilters);
     } else {
        compositeFilter = new CompositeAnyFilter(modelFilters);
     }
     //Only highlights text from the first filter
     HighlightTextRenderer renderer = _olv.DefaultRenderer as HighlightTextRenderer;
     if (renderer != null) {
        SolidBrush brush = renderer.FillBrush as SolidBrush ?? new SolidBrush(Color.Transparent);
        if (brush.Color != Color.LightSeaGreen) {
           brush.Color = Color.LightSeaGreen;
           renderer.FillBrush = brush;
           _olv.DefaultRenderer = renderer;
        }
     } else {
        MessageBox.Show(@"Renderer is null!");
     }
     _olv.ModelFilter = compositeFilter;
  }

Solution

  • This solution works for me. Multiple columns support still with highlighting support.

    var filters = new List<IModelFilter>();
    TextMatchFilter highlightingFilter = null;
    if (!String.IsNullOrEmpty(txtSearch.Text))
    {
        var words = txtSearch.Text.Trim().Split(null);
        highlightingFilter = TextMatchFilter.Contains(ListView, words);
        foreach (var word in words)
        {
            var filter = TextMatchFilter.Contains(ListView, word);
            filters.Add(filter);
        }
    }
    var compositeFilter = new CompositeAllFilter(filters);
    
    ListView.ModelFilter = highlightingFilter;
    ListView.AdditionalFilter = compositeFilter;
    ListView.DefaultRenderer = new HighlightTextRenderer(highlightingFilter);