Wiring up an AutoCompleteBox to a JSON Service in Silverlight

I’m currently building an internal application for The Code Project that needs to be able to transfer the contents of some potentially very large files over the wire.  After considering various ways to get the data from point A to point B, we decided the easiest thing would be to process the text file on the client, and send batches of rows up to the server for processing.  Initially we looked at building a WPF client for this, but then switched over to Silverlight 4 since the rest of the application is web-based and we didn’t want staff to have to worry about a separate standalone application.

Basically the files get translated into simple lists on the server, so the UI simply consists of “Enter/choose a list” and a drag-and-drop file uploader.  The list selection UI needs to support both selection from existing lists, or creation of new lists.  To that end, I did some searching for an AutoCompleteTextBox in Silverlight, and found Jeff Wilcox’s article on Introducing the AutoCompleteBox.  Of course, it doesn’t show how to wire up the contents to a JSON call, so another search yielded Tim Heuer’s article on Making Use of JSON data in Silverlight.  Putting them together, you get something that works quite well for what I need.

Here’s my XAML for the AutoCompleteBox:

<sdk:AutoCompleteBox Height="20" HorizontalAlignment="Left" 
Margin="12,0,0,0" 
Name="autoCompleteBox1" VerticalAlignment="Top" 
Width="376" Grid.Row="1"
ValueMemberBinding="{Binding Name}" >
   <sdk:AutoCompleteBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"></TextBlock>
        </DataTemplate>
   </sdk:AutoCompleteBox.ItemTemplate>
</sdk:AutoCompleteBox>

Note: I’m not a Silverlight expert, so if I’m doing things against best practices, I apologize.  It does, however, work for me as shown.  I wired up the loading of the AutoCompleteBox in my form’s load, since it’s the only thing this page does so I saw no point in doing it lazily when the AutoCompleteBox is used.  I simply added Loaded=”UserControl_Loaded” to my root UserControl element for this.

Then in the MainPage.xaml.cs, I implemented this Loaded handler like so:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    WebClient proxy = new WebClient();
    string url = String.Format("{0}/Test/ListSuppressionLists", Constants.SERVICEHOSTNAME);
    proxy.OpenReadCompleted += new OpenReadCompletedEventHandler(proxy_OpenReadCompleted);
    proxy.OpenReadAsync(new Uri(url));
}
 
void proxy_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    Stream myStream = e.Result;
    var serializer = new DataContractJsonSerializer(typeof(SuppressionList[]));
    SuppressionList[] lists = (SuppressionList[]) serializer.ReadObject(myStream);
    autoCompleteBox1.ItemsSource = lists;
}

All that remains is to implement a controller in the ASP.NET MVC application that this Silverlight control will live in (and make sure it has the clientaccesspolicy.xml and crossdomain.xml files, if needed).  The controller action needs to AllowGet with its JsonResult, too.  Here’s basically what it looks like:

public JsonResult ListSuppressionLists()
{
    // _repository is provided via the Controller constructor and IOC
    return Json(_repository.ListReadOnly(), JsonRequestBehavior.AllowGet);
}

Here’s the result in action:

image

blog comments powered by Disqus