Automatically Filtering a ComboBox in WPF
Haven't you always wanted to use a combo box like the one in Start menu's Run dialog?
A client asked me for the exact same thing, and now you can download it from here too. The Automatically Filtered ComboBox inherits from the original ComboBox and adds the auto-filtering, along with an ability to filter while ignoring case. The IsTextSearchEnabled property already allows you to do all this (and the use of which is therefore supported), but it doesn't allow for case sensitivity and filtration of the results.
Interesting bits about the code:
/// Gets the text box in charge of the editable portion of the combo box.
protected TextBox EditableTextBox
The above section of code lets you access the text box that sits at the top of the combo box. We use this text box to get the selection (just like what we could get from a ComboBox in Windows Forms using the SelectedText property).
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
view.Filter += this.FilterPredicate;
ICollectionView view = CollectionViewSource.GetDefaultView(this.ItemsSource);
The above two piece of code use the CollectionViewSource class to create a filter on the default view of the ItemsSource. This mechanism is used internally by the original ComboBox to filter and/or sort the source of the items. I'm a bit baffled by why the WPF team would decide on only using a single, global view for the items' source, rather than a model like the one presented in ADO.NET using the DataView on DataTables. Thanks to Tomer for the heads up on that one.
private bool FilterPredicate(object value)
// We don't like nulls.
if (value == null)
// If there is no text, there's no reason to filter.
if (this.Text.Length == 0)
string prefix = this.Text;
// If the end of the text is selected, do not mind it.
if (this.length > 0 && this.start + this.length == this.Text.Length)
prefix = prefix.Substring(0, this.start);
.StartsWith(prefix, !this.IsCaseSensitive, CultureInfo.CurrentCulture);
The above is the predicate for filtering. As you can see, only items that start with the text already in the box are kept in the list (Yes, value.ToString() is not a correct implementation; I will change it in the future). Notice that if the selection is on the end of the text, we do not use that part for the search, since the very next character pressed will replace the selected text and we would like to show the possible results for such a keystroke.
As I am still in the process of getting used to WPF, there is still much to learn. I would gladly accept any comment you may have about the means to the end and also on my style and conventions. You always have something new to learn :)