← About Jeff

AutoCompleteBox tip: Writing a new text filter in VB

January 5, 2009

The default text filter used in the AutoCompleteBox control works well in most situations. I'd like to share an improvement that adds search engine-like "AND" operator support.

In this short guide, we'll change the text filter to support search strings like "b gates" matching to "bill gates" by splitting the search words and using them as independent lookups.

This example contains Visual Basic code that should be easily translatable to C#.

The default text filter

The default filter in AutoCompleteBox is a text filter that returns a value indicating whether the string is a suggestion. It is a "StartsWith" check, and uses the current culture for its comparison.

When you set or change the SearchMode dependency property on AutoCompleteBox, most SearchMode values will change the TextFilter property to one of the built-in filters - this happens behind the scenes.

You can set the TextFilter property to your own text-based algorithm or code to improve the experience, if you change the SearchMode to Custom.

Allowing partial word matches ("AND" operator)

For partial word matches, the idea is that the search string is split up into multiple words, each then used with an AND operator to determine matches.

The default filter understands spaces as literal characters, so a search for "microsoft silverlight" will literally only match a string that starts with "microsoft silverlight". Ideally, the text filter would let "soft silver" match the item text "microsoft silverlight".

These examples all set the TextFilter value of an auto complete instance in the Loaded event of the Silverlight Application's page.

These assume that you've already created your Silverlight Application project in Visual Studio, added a reference to the toolkit's Microsoft.Windows.Controls.dll library, added the xmlns "controls" to the page, and included an auto complete box control instance named "autoComplete1".

VB

Define the word-splitting text filter:

    ' Splits the search string into words and returns true if the value contains
    ' them all.
    Function SplitWords(ByVal search As String, ByVal value As String)
        Dim words() As String
        value = value.ToLower
        words = search.Split(" ", StringSplitOptions.RemoveEmptyEntries)

        If words.Length = 0 Then Return False
        For Each searchWord As String In words
            searchWord = searchWord.ToLower
            If Not value.Contains(searchWord) Then
                Return False
            End If
        Next
        Return True
    End Function

During page load, setup the text filter (also adds some sample data):

    Sub OnLoaded(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Loaded
        autoComplete1.SearchMode = AutoCompleteSearchMode.Custom
        autoComplete1.TextFilter = AddressOf SplitWords

        Dim list As New List(Of String)
        list.Add("Steve Ballmer")
        list.Add("Bill Gates")
        autoComplete1.ItemsSource = list
    End Sub

Allowing any word matches ("OR" operator)

VB

Here's the SplitWords function, updated to instead match any of the words in the search string, instead of them all:

    ' Splits the search string into words and returns true if the value contains
    ' at least one of them. Different from the first sample.
    Function AnySplitWord(ByVal search As String, ByVal value As String)
        Dim words() As String
        value = value.ToLower
        words = search.Split(" ", StringSplitOptions.RemoveEmptyEntries)

        If words.Length = 0 Then Return False
        For Each searchWord As String In words
            searchWord = searchWord.ToLower

            ' At least one was found!
            If value.Contains(searchWord) Then
                Return True
            End If
        Next

        ' None were matched
        Return False
    End Function

How TextFilter is different from ItemFilter

TextFilter takes a method or delegate that takes in two parameters: the search string, and the current item's text value. The item's text value is found by either using the optional Converter parameters on the control, or it will simply fall back to calling the ToString() method on the object. It returns a bool value indicating whether it is in the search.

The alternative ItemFilter is similar, but does not operate on string values for individual items. Instead, the 2nd parameter is a object type and represents the bound business object itself. The filter should return true when the item should be considered a suggestion.

If, and only if, you set the SearchMode to 'Custom', will the alternative ItemFilter property be used for determining suggestions.

In most apps, ItemFilter is your best bet for sophisticated business object lookups and decisions.

Download the December 2008 release of the Silverlight Toolkit

Hope this helps.