Consider the following scenario:
-
I have a
ListViewthat is bound to anObservableCollectionusing theDataContext:<ListView ItemsSource="{Binding}">The
classcontaining thestringdata uses theDependencyPropertymechanism to keep the displayed content synced with the data collection. - The
ListViewhas one column that is editable (I followed the tutorial here to achieve this); theListViewItemis then either aTextBlockor aTextBox. This is done using aDataTemplateand twoStyleresources. - I’d like to format the string displayed in the
TextBlockbased on a search string. Specifically, I’d like to format the items of theListViewto become bold as the user types in their search query if there is a match (only the characters that match in sequence should be made bold). This only needs to be displayed for the text currently being rendered using theTextBlock(that is, text not currently being edited).
I’ve considered using an IMultiValueConverter that takes in a reference to the TextBlock that renders the data so that I can format the text appropriately. However, this will destroy the binding that I’ve set up:
<TextBlock.Text>
<MultiBinding Converter="{StaticResource searchFormatter}" ConverterParameter="{x:Reference Name=txtSearch}">
<MultiBinding.Bindings>
<Binding Path="NameOfBoundDependencyProperty"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding.Bindings>
</MultiBinding>
</TextBlock.Text>
searchFormatter being the IMultiValueConverter and txtSearch being the TextBox containing the search query.
I’m still learning WPF so I’m not familiar with the best approach or to what’s possible. Is there a way to keep the data bound (so that edits reflect in the collection and the ListView) and still represent the data differently to the user (so that search matches may be bold)? Perhaps it would be cleaner if I manage the binding manually?
I decided to use a
Controlthat supports HTML so that I could use anIValueConverterto update the value of the displayed text on the fly without affecting any active bindings. I used the code from here and modified it so that it looked like aTextBlockwithin myListView:However, I still needed to trigger the
IValueConverterso that the display is updated as the user types in their search query (code from here):I didn’t want to slow down the search process so I only forced this refresh if there was actually a match (or if the state of having a match moves to no match). My
IValueConvertorsimply inserted the bold tags to match the search query:Where
searchFormatterthis time is anIValueConvertor.