Reputation: 2273
I have an ItemsSource
bound up to my data. I have a TextBox
that as the user starts typing it in, I filter the items based on the following Filter predicate
on the textBoxText
changed event:
ICollectionView listView = CollectionViewSource.GetDefaultView(myControl.ItemsSource);
listView.Filter = ((x) =>
{
MyData data = x as MyData;
return data.Name.Contains(searchString, System.StringComparison.InvariantCultureIgnoreCase);
});
This works fine and filters the list. However I also want the items to highlight in yellow the entered search criteria as they type. How can I do that in wpf? Kind of like:
If i searched for "est" and the item is Forest
The Forest item highlights est
in yellow or any other color in the ListBox
? Thanks for any suggestions.
Upvotes: 1
Views: 801
Reputation: 2099
I achieved this by creating a custom control - HighlightableTextBlock
that inherits from TextBlock
and adds the following dependency property:
public string HighlightSource
{
get { return (string)GetValue(HighlightSourceProperty); }
set { SetValue(HighlightSourceProperty, value); }
}
public static readonly DependencyProperty HighlightSourceProperty =
DependencyProperty.Register("HighlightSource", typeof(string), typeof(HighlightableTextBlock), new PropertyMetadata("", OnChange));
Performing the actual highlighting in the OnChange
event handler:
static void OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as HighlightableTextBlock;
var text = textBlock.Text;
var source = textBlock.HighlightSource;
if (!string.IsNullOrWhiteSpace(source) && !string.IsNullOrWhiteSpace(text))
{
var index = text.IndexOf(source);
if (index >= 0)
{
var start = text.Substring(0, index);
var match = text.Substring(index, source.Length);
var end = text.Substring(index + source.Length);
textBlock.Inlines.Clear();
textBlock.Inlines.Add(new Run(start));
textBlock.Inlines.Add(new Run(match) { Foreground = Brushes.Red });
textBlock.Inlines.Add(new Run(end));
}
}
}
And the markup side of things looks like this:
<controls:HighlightableTextBlock Text="{Binding SomeText}"
HighlightSource="{Binding ElementName=SearchTextBox, Path=Text}">
</controls:HighlightableTextBlock>
Seems to be working for me. I've hardcoded the color of the matched substring in this example, but you can add a separate property if you want to pass that from the markup as well.
Hope this helps...
Upvotes: 1