Introduction
An alternative implementation of Jan Vilášek's article located
here: Highlight-Searched-Text-in-WPF-ListView
This is how to filter + sort thousands of items while also highlighting text which matches your search phrase while also utilizing virtualization so that
WPF programs don't run poorer then usual.
New in this nearly 100% original and rewritten variation is:
- The ability to search and filter out items that don't match.
- The ability to sort the items by clicking the column header of the listview.
- A highly efficient implementation that does not rely on recursion to apply the highlighting effect.
- An example of a "WPF Custom Control Class Library"!! (all you need to know is it's just a regular class library, but you need to configure its AssemblyInfo.cs
and have a "Themes" folder with a "Generic.xaml" to make it work).
Using the code
The program is very simple to use. Simply type some text into the search box and the number of items which are available to the listview for viewing will
be limited so only those items which contain your search request will be visible. In addition you can click the "First Name" and "Last Name" columns to sort the items.
The HighlightTextBox
control that was created for this project is also highly reusable for other applications so it's worthwhile to get acquainted with
its simple design and use:
To use this control, simply specify what you want to highlight with the HighlightPhrase
property and if this string fragment is contained in the Text
property then
it will be highlighted using the HighlightBrush
.
This control was used in the DataTemplate's of the listview to define how to handle the rendering of listview
items dynamically. Here is a minimal representation of the actual XAML:
<ListView Name="listView"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListView.View>
<GridView>
<GridViewColumn Width="200">
<GridViewColumnHeader Content="First Name" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<controls:HighlightTextBlock Text="{Binding Path=FirstName}"
HighlightPhrase="{Binding ElementName=textBoxSearch, Path=Text}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="200">
<GridViewColumnHeader Content="Last Name" />
<GridViewColumn.CellTemplate>
<DataTemplate>
<controls:HighlightTextBlock Text="{Binding Path=LastName}"
HighlightPhrase="{Binding ElementName=textBoxSearch, Path=Text}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Points of Interest
One thing I learned while writing this code is potentially the solution to this
problem: WPF ListBox VirtualizingStackPanel.VirtualizationMode=“Recycling”
causes same list items to always appear when scrolling.
Now I didn't encounter the exact same issue, but I did
encounter similar behavior, i.e. setting the virtualization mode to standard stops the problem (but hurts performance) and it only happens when scrolling.
In my version of the problem the highlighting wasn't showing up when you rapidly scrolled through items, but for the items that you could see when you first typed
in the search box it worked perfectly.
The solution was overloading the "Text
" and "TextProperty
" of HighlightTextBox
and setting
a PropertyChangedCallback
which caused the highlighting to be re-applied when the text is changed (i know, this seems like a nobrainer now because the lack of this code
is definitely a bug because you need to update the highlighting if the text changes just as much as you need to update it if the highlight phrase changes,
but it's amazing how far I got with what seemed like otherwise perfect code to only see the problem when scrolling in recycling-virtualization mode).
The reason the new "Text
" property fixes the problem is because when you scroll, while in recycling-virtualization mode, the existing instances
of HighlightTextBox
's are getting their Text
property set, and perhaps i was expecting the HighlightPhrase property to also get set but that only actually happens
(as per my binding in MainWindow.xaml) when you type in that search textbox.
So to summarize: If you have any issues in recycling mode, it's the control
you use in your DataTemplate that needs fixing.
History
- June 25th 2010 : Fixed bug. Also cleaned up the code + added a way to see the virtualization in action, i.e. more detailed information in the window title.
- June 24th 2012 : Initial post.