Thursday, September 13, 2012

Implementing an Autosuggest Textbox in Silverlight

Showing suggestions from database for each user input in textbox.
Download Sample Project RadAutoSuggestBox
Introduction
The auto complete or can say autosuggest pattern is well-known, used from long and supported in almost all technologies. In Silverlight Toolkit you can see AutoCompleteBox it provides two type of suggestions one from already bound collection and another from database by hooking it with RIA service. But if you need to get suggestions from database by using WCF service or any other conventional way then you need to tweak the logic. Here I am going to demonstrate how you can tweak Telerik RadComboBox to use for this scenario. You can also try this type of logic for Silverlight toolkit AutoCompleteBox.

Background
To implement this application, I am going to use the following technologies:
  • Silverlight5 for the client tier
  • WCF services -HTTP Binding
  • Telerik RadControls for Silverlight v2012.1.215.1050
  • .NET Framework v4.0.30319
Silverlight Business Application
Create new Silverlight application. Name it to ‘RadAutoSuggestBox’.



WCF Service
Add WCF service to the solution. Name it ‘WcfService1’.

Write one method to return collection as per user input parameter in ‘Service1.svc.cs’
        
public List<string> SuggestOption(string x)
        {
            List<string> lst = new List<string>();//Make a call to database to get collection
            lst.Add("Omaha via webex");
            lst.Add("Celine Robinson");
            lst.Add("Vanessa Johnson");
            lst.Add("Susan Peter");
            lst.Add("Nedra Tracy");
            lst.Add("Diane Houston");
            lst.Add("Nancy McEvoy");
            lst.Add("San Francisco");
            var result = lst.Where(x1 => x1.ToLower().Contains(x.ToLower()));
            return result.ToList<string>();
        }
Add contract for this method.
        [OperationContract]        
        List<string> SuggestOption(string x);

To enable a Silverlight control to access a service in another domain, the service must explicitly opt-in to allow cross-domain access. I am also going to deploy WCF service and Silverlight application on different servers.

Add ‘CrossDomainService’ service and add following code to it.

public class CrossDomainService : ICrossDomainService
    {
        Message ICrossDomainService.ProvidePolicyFile()
        {
            FileStream filestream = File.Open(@"ClientAccessPolicy.xml", FileMode.Open);
            // Either specify ClientAccessPolicy.xml file path properly
            // or put that in \Bin folder of the console application
            XmlReader reader = XmlReader.Create(filestream);
            System.ServiceModel.Channels.Message result = Message.CreateMessage(MessageVersion.None, "", reader);
            return result;
        }
    }

Create contract for this service.
[ServiceContract]
    public interface ICrossDomainService
    {
        [OperationContract]
        [WebGet(UriTemplate = "ClientAccessPolicy.xml")]
        Message ProvidePolicyFile();
    }

Add ‘ClientAccessPolicy.xml’ file for policy description.
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

Silverlight Client
Add service reference to Silverlight project.


Now add View model class named ‘MainViewModel’ to call WCF service model. We are implementing ‘INotifyPropertyChanged’ interface. Also defining following three properties:
RadComboBoxText – We shall bind this property to Text property of telerik combo box control so it can get user input text.  Further this user entered text is passed as a parameter to WCF service method.
ItemCollection – This is the collection which is bound to ItemSource of telerik combo box. We are going to change it for each character entered.
IsDropDownOpenState - this property is used to open the dropdown and bound to IsDropDownOpen property of Rad Combobox.

Set datacontext of existing view(created with project template) ‘MainPage.xaml’ to this view model.
           
               //ViewModel setting in constructor 
               var viewModel = new MainViewModel(); 
               this.DataContext = viewModel;

Add RadComboBox to MainPage.xaml and viewmodel properties as follows.
            
<telerik:RadComboBox x:Name="RadComboBox1" TextSearchMode="Contains" CanKeyboardNavigationSelectItems="False" EmptyText="Search Text" ItemsSource="{Binding ItemCollection, Mode=OneWay}" IsEditable="True" IsTextSearchEnabled="True" Text="{Binding RadComboBoxText, Mode=TwoWay}" IsDropDownOpen="{Binding IsDropDownOpenState, Mode=TwoWay}" IsFilteringEnabled="True" CanAutocompleteSelectItems="True" IsMouseWheelEnabled="True" Margin="0 10 0 10" VerticalAlignment="Center" Canvas.Left="149" Canvas.Top="102" Width="229" />

 
Now if you run the application it will look like this.

There is arrow icon which we are not going to use so need to be removed. Open this application in Expression Blend and modify the template to get rid of this arrow. I am not going in detail how to do in expression blend. After template modification UI will be as follows.

This implementation gets data from database for each user input. It supports keyboard navigation too.


Note
You can download source code attached with this article. Hope this article will help you in implementing AutoComplete textbox.
I would appreciate Vote for the Article and any comments or concerns or how things could be done better.
Thanks for reading.

Tag: Autosuggest dropdown, Autosuggest combobox, Autosuggest textbox, Keyboard support in autosuggest textbox, AutoComplete  with WCF, How to create Silverlight autosuggest control, Auto-suggest Control with WCF, Introducing the AutoCompleteBox, Implementing AutoComplete Text Functionality in Silverlight, AutoCompleteBox in Silverlight, Telerik autosuggest with WCF, Using WCF with Autosuggest textbox. MVVM with autosuggest.