The AutoCompleteTextBox is a great tool in Silverlight to allow you to provide relevant information to your users as they are typing as seen below:

But there are a few issues with this control
- Pretty much every sample on the net uses the code behind to do the heavy lifting and not binding
- It will not update the VM text box in real time, which is needed if you want to do on the fly filtering
In this post I will walk you though how to setup your AutoCompleteText box and we will learn how to do 3 things
- Use MVVM to populate and use the control
- Use a custom Behavior to allow the property backing the control to be updated in real time
- Use a command to trigger background searches on the fly
Using MVVM to populate your control:
In order to populate your AutoCompleteTextBox you will need to bind something to the ItemSource property of the control as such:
ItemsSource="{Binding KeywordSearchSource}"
I am sure you are wondering what the KeywordSearchSource is? Well it is simple a property which returns a IEnumerable<string>
public IEnumerable KeywordSearchSource
{
get
{
return SomeListOfValues.Select( x => x.TextValue );
}
}
The next thing you will want to do is setup a property in your view to handle the current value inside the control. This is needed because we are binding and not using the code behind. You can do this as below:
Text="{Binding KeywordSearchText, Mode=TwoWay}"
The trick to above is to remember to mark this as being TwoWay or you will not get the results you are expecting
private string _keywordSearchText;
public string KeywordSearchText
{
get { return _keywordSearchText; }
set
{
_keywordSearchText = value;
NotifyOfPropertyChange(() => KeywordSearchText);
}
}
That does it for the MVVM portion of the setup. However, you may already know that when binding to a text box the actual binding does not trigger until AFTER the user leaves the control, in many cases this is good but not in our case. In our case I want to start the filter process as the user types (which is fine as I have all the filter data local, this is NOT fine if I have to do any type of remote call to filter the data as this will cause a bad user experience).
Triggering the binding in real time:
As I stated above the binding of a text box (or autocomplete text box) does not fire until you leave the control and this is not the desired action for us. In order to get around this we are going to create a custom behavior to allow the text box binding to push the value into our property in real time.
Our custom behavior is going to be called the ImmediateUpdateBehavior and the code can be found below.
public class ImmediateUpdateBehavior : Behavior
{
protected override void OnAttached()
{
AssociatedObject.TextChanged += OnTextChanged;
}
void OnTextChanged(object sender, RoutedEventArgs e)
{
AssociatedObject.GetBindingExpression(AutoCompleteBox.TextProperty).UpdateSource();
}
protected override void OnDetaching()
{
AssociatedObject.TextChanged -= OnTextChanged;
}
}
In the behavior above you can see that all we are pretty much doing is listing for the TextChanged event and forcing the binding to fire. This is a nice way to do it when developing with MVVM.
Once we have our behavior created we need to attach it to our AutoCompleteTextBox and that can be found below.

Triggering the filtering to fire as we type:
I am going to chose to do this via a Command. I guess you could have the changing value of the property do the same thing but I typically am against doing this as I feel it is hiding the implementation details of the filtering. I also feel that this can cause unwanted side effects in your code if you are not careful.
In order to use the command I am going to use the EventTrigger behavior in silverlight to call my command. You can see this XAML below.

In the XAML above you see I am calling the KeywordSearchFilterCommand. This command will end up calling the code below
private void KeywordSearchFilter()
{
// Key here is i am simply notifying to rebuind these values and allowing the underlying methods to filter the data
NotifyOfPropertyChange(() => SomeListOfValues);
NotifyOfPropertyChange(() => PagedSomeListOfValues);
}
As you can see from the above I am not doing anything special in the filter method I am simply notifying of property change and letting the various properties doing their own filtering. The code below is the filtering for my PagedSomeListOfValues property (we are doing client side paging here)
public ObservableCollection PagedSomeListOfValues
{
get
{
var skipCount = PageIndex > 0 ? PageIndex * PageSize : 0;
var takeCount = PageSize;
var tempItems= SomeListOfValues.Skip(skipCount).Take(takeCount).ToList();
var observableLinks = new ObservableCollection();
observableLinks.SetContents(tempItems);
return observableLinks;
}
}
Once you have your 2 properties (list and search field) bound to the AutoCompleteTextBox you are almost there, but not quite. In order to make this fully work you will want to also you the custom behavior and the filter command.
Hope this helps.
Till next time,
Posted
11-18-2011 4:25 PM
by
Derik Whittaker