Advertisement

Getting started with Silverlight: Part 4 – Binding the data and storing some for later

This is part 4 in a series on getting started with Silverlight.  To view the index to the series click hereYou can download the completed project files for this sample application in C# or Visual Basic.

In the previous step 3 we did a lot of work to get back our data from a public web service and display it in a control.  The DataGrid control we used, however, isn’t really the UI we’re looking for so let’s define what we want.  To do this we’re going to use an ItemsControl and a DataTemplate.  This will introduce us to XAML binding syntax and how to leverage more powerful data binding information.

Starting the UI over – delete the DataGrid

Well, after all that work, let’s delete the DataGrid and just the DataGrid.  We won’t be needing the assembly reference or the xmlns:data values anymore as well, so go ahead and remove them.

Replace the DataGrid with an ItemsControl like this:

   1: <ItemsControl x:Name="SearchResults" Margin="0,8,0,0" Grid.Row="1" />

Now here is where Blend is going to be helpful for us again.  Go into Blend and we’re going to modify the ItemTemplate for the ItemsControl.  ItemsControl is just essentially a rendering control that does what we tell it to.  If we do nothing but change the DataGrid to an ItemsControl and run our application this is what we’ll get:

ItemsControl rendering with no template

The ItemsControl has no idea how we want to display the data, so we have to tell it how in a template…back to Blend.  The general concept we’re going to go for is this (repeated of course):

ItemsControl template mockup

where the box is the avatar of the user posting the message.  Using our knowledge of layout from the previous steps we can create the template easily.  In Blend, locate the SearchResults object in the tree and right click to edit the ItemsTemplate (under the Generated Templates section):

Edit Generated Items menu option

we now have an empty template we can put stuff in.  I called mine SearchResultsTemplate in the dialog that came up.  Now we are in layout editing mode and can drag/move/etc items in our layout.  I created a Grid-based layout and here’s my resulting XAML for the template:

   1: <DataTemplate x:Key="SearchResultsTemplate">
   2:     <Grid Margin="4,0,4,8" d:DesignWidth="446" d:DesignHeight="68">
   3:         <Grid.ColumnDefinitions>
   4:             <ColumnDefinition Width="Auto" />
   5:             <ColumnDefinition Width="*" />
   6:         </Grid.ColumnDefinitions>
   7:         <Border VerticalAlignment="Top" Margin="8" Padding="2" Background="White">
   8:             <Image Width="40" Height="40" />
   9:         </Border>
  10:  
  11:         <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="0,4,0,0">
  12:             <TextBlock x:Name="AuthorName" FontWeight="Bold" />
  13:             <Grid Margin="0,6,0,0">
  14:                 <Grid.RowDefinitions>
  15:                     <RowDefinition Height="Auto" />
  16:                     <RowDefinition Height="2" />
  17:                     <RowDefinition Height="Auto" />
  18:                 </Grid.RowDefinitions>
  19:                 <TextBlock x:Name="TweetMessage" TextWrapping="Wrap" />
  20:                 <TextBlock x:Name="PublishDateLabel" Grid.Row="2"  />
  21:             </Grid>
  22:         </StackPanel>
  23:     </Grid>
  24: </DataTemplate>

I’m also putting the ItemsControl itself into a ScrollViewer since the ItemsControl doesn’t natively provide a scrolling view:

   1: <ScrollViewer Grid.Row="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" BorderThickness="1">
   2:         <ItemsControl x:Name="SearchResults" Margin="0,8,0,0" Grid.Row="1" ItemTemplate="{StaticResource SearchResultsTemplate}" />
   3:     </ScrollViewer>

Now all we have is a template, but we have to tell that template what to do with the data it will be receiving.

The XAML binding syntax

Here’s where our binding syntax is going to come in.  You see, ItemsControl is getting data to it (remember we haven’t changed our code so the SearchResults.ItemsSource is still being set to our PagedCollectionView.  To map our model elements to our template we need to use Binding.  The basic XAML binding syntax is:

{Binding Path=<some-data-path>, Mode=<binding mode>}

There are more advanced features you could get into, but this is the basic and we’ll start here.  For instance, to bind our Image element in our template to our Avatar from TwitterSearchResult model, it will look like this:

   1: <Image Width="40" Height="40" Source="{Binding Path=Avatar, Mode=OneWay}" />

And to bind the Author to the AuthorName element like this:

   1: <TextBlock x:Name="AuthorName" FontWeight="Bold" Text="{Binding Path=Author, Mode=OneWay}" />

In both of these we are using OneWay syntax because we don’t need to have it be TwoWay as we aren’t changing data back.  For the PublishDate, we want to provide some explicit formatting of the data.  We can do this through Value Converters.

Building a Value Converter

Value converters are classes that implement IValueConverter, which provides a Convert and ConvertBack methods.  For our PublishDate we’re going to basically allow explicit formatting of the DateTime object.  We’ll create a DateTimeConverter.cs class in a folder in our project called Converters.  The class looks like this:

   1: using System;
   2: using System.Threading;
   3: using System.Windows.Data;
   4:  
   5: namespace TwitterSearchMonitor.Converters
   6: {
   7:     /*
   8:      * Use this converter for formatting dates in XAML databinding
   9:      * Example:
  10:      *  Text="{Binding Path=PublishDate, Converter={StaticResource DateTimeFormatter}, ConverterParameter=MMM yy}" />
  11:      * 
  12:      * */
  13:     public class DateTimeConverter : IValueConverter
  14:     {
  15:         #region IValueConverter Members
  16:  
  17:         public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  18:         {
  19:             DateTime? bindingDate = value as DateTime?;
  20:  
  21:             if (culture == null)
  22:             {
  23:                 culture = Thread.CurrentThread.CurrentUICulture;
  24:             }
  25:  
  26:             if (bindingDate != null)
  27:             {
  28:                 string dateTimeFormat = parameter as string;
  29:                 return bindingDate.Value.ToString(dateTimeFormat, culture);
  30:             }
  31:  
  32:             return string.Empty;
  33:         }
  34:  
  35:         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  36:         {
  37:             throw new NotImplementedException();
  38:         }
  39:  
  40:         #endregion
  41:     }
  42: }

Now to use this we'll go back to our XAML page that will be using this (Search.xaml) and add an xmlns declaration and a resource.  The xmlns we’ll use looks like this:

   1: xmlns:converters="clr-namespace:TwitterSearchMonitor.Converters"

and then in the Resources section of the XAML (where the other template is defined) we’ll add a resource that points to the converter:

   1: <navigation:Page.Resources>
   2:         <converters:DateTimeConverter x:Key="DateTimeFormatter" />
   3: ...

With these two things in place we can use our converter on our PublishDateLabel element like this:

   1: <TextBlock x:Name="PublishDateLabel" Text="{Binding Path=PublishDate, 
   2:         Converter={StaticResource DateTimeFormatter},
   3:         ConverterParameter=dd-MMM-yyyy hh:mm tt}" Grid.Row="2"  />

This tells XAML that it should run the IValueConverter to get the rendered output.  Our result is the explicit formatting of data that we want.  The result of all this additional syntax for binding now shows the rendering in our desired mockup:

Rendered ItemsControl data template

(yes I know that ‘twitpic’ as a search shows some interesting results…but you can count on it to have fast refreshing data as a search term!)

Great!  That wasn’t that difficult, was it?  This binding syntax will be essential to building applications for you.

Storing some settings and configuration data

One of the things that would be helpful for our application is to store the last tweet ID so that the next time the application is run, we can start where we left off without starting over.  Additionally it would be cool to save the search term history so that we can view it in our History navigation point later.

To accomplish this, we’ll be using Isolated Storage available in Silverlight.  Isolated Storage enables a low-trust user-specific location for storing simple data.  For some more information on Isolated Storage:

To do this I’m going to add a Helper class to our Model folder.  This helper class will assist us in saving/reading data from our isolated storage location.  The basics of IsolatedStorage are that you create a file to which you can read data from or write data to if you want.  In our use we’ll use IsolatedStorageSettings for saving simple name/value pair data (search term/last ID).  Here’s the contents of the Helper.cs class:

   1: using System.IO.IsolatedStorage;
   2:  
   3: namespace TwitterSearchMonitor.Model
   4: {
   5:     public class Helper
   6:     {
   7:         internal static string GetLatestTweetId(string searchTerm)
   8:         {
   9:             if (IsolatedStorageSettings.ApplicationSettings.Contains(searchTerm))
  10:             {
  11:                 return IsolatedStorageSettings.ApplicationSettings[searchTerm].ToString();
  12:             }
  13:             else
  14:             {
  15:                 return "0";
  16:             }
  17:         }
  18:  
  19:         internal static void SaveLatestTweetId(string searchTerm, string latestId)
  20:         {
  21:             if (IsolatedStorageSettings.ApplicationSettings.Contains(searchTerm))
  22:             {
  23:                 IsolatedStorageSettings.ApplicationSettings[searchTerm] = latestId;
  24:             }
  25:             else
  26:             {
  27:                 IsolatedStorageSettings.ApplicationSettings.Add(searchTerm, latestId);
  28:             }
  29:         }
  30:     }
  31: }

Now in our Search.xaml.cs we’ll add the following in SearchForTweetsEx after the activity indicator is set:

   1: _lastId = Helper.GetLatestTweetId(SearchTerm.Text); // get the latest ID from settings
   2:  
   3: Helper.SaveLatestTweetId(SearchTerm.Text, _lastId); // saving for history even if a result isn't found

and then in the OnReadCompleted after we close the XmlReader we’ll add this:

   1: Helper.SaveLatestTweetId(SearchTerm.Text, _lastId); //saving last tweet id

And that now saves the search terms used as well as the last ID found if a result was found.

Summary

In this step we’ve set up a data template for a control, used some simple data binding using the XAML declarative syntax, added a value converter to format our view of information and save settings information to a local storage mechanism.

We’ve got basically our application working, so let’s start adding some interesting polish to the UI.

Let’s move on to part 5 where we add some new controls to enhance the experience using the data we just stored in this step.


This work is licensed under a Creative Commons Attribution By license.

  1. Gravatar
    10/7/2009 1:38 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Great tutorial! One problem. You left out binding the tweet itself to the TweetMessage block.
  2. 10/7/2009 2:01 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Rob -- eek, thanks for the note...will try to correct (I know it is valid in the code download though).
  3. 10/14/2009 1:29 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Hi, here is the code missing:

    <TextBlock x:Name="TweetMessage" Text="{Binding Path=Tweet, Mode=OneWay}" TextWrapping="Wrap" />
  4. 10/26/2009 2:21 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Thanks for the awesome tutorial. And I want to ask if it is possible to customize each item's style in the ItemsControl, say alternating background color, or make a specific people name italic?
  5. 10/26/2009 9:28 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Kelvin - I don't know if ItemsControl enables alternating colors I'd have to check. One thing about the specific people name though is you could use a ValueConverter as we did with the time. You can put your code to check if the person should be italics and then return that information.
  6. Gravatar
    10/27/2009 2:21 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    y78
  7. 10/29/2009 10:02 AM | # jatftt - just another thanks for this tutorial
    Hi, these are some great tutorials for us Silverlight beginners... and even though I wanted to thank you at the end of the 7 tutorials, finally I decided to thank you right now. Keep on going like this. Even though I truly believe it's a great effort to write them.

    P.S.: I wonder if Hilkee got his watch after all...
  8. 11/13/2009 2:17 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Thank you very much for these tutorials, definitely it is a good starting point. I ended up a little bit confused on the part 3 though, I'm not used to async programming. I'll put more time on it.

    Keep up the good work!
  9. 11/13/2009 2:33 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Sicofonia - agreed -- you're likely coming from the web development world (like I was) -- and this will be one of your larger paradigms to shift to -- once you do, it will be more natural :-)
  10. 11/18/2009 9:20 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Very clear and informative tutorial. It's my first attempt with Silverlight and I learned a lot. Thanks.

    Only one problem: For some reason I didn't get any Avatar images displayed. I checked the binding syntax carefully and couldn't find anything different to your code. I also set a breakpoint in the foreach loop in OnReadCompleted and the image URLs were returned and were viewable in IE, but nothing was displayed in the Silverlight app. Strange.
  11. 11/26/2009 1:02 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    i have the same problem :didn't get any Avatar images displayed.
  12. 12/30/2009 3:58 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    @Steve, vince - Please check whether u are populating the Avatar properly... Check
    "Populating our ObservableCollection" session of the previous tutorial. The second link is the syndication is the image. (You might be using "Avatar = new BitmapImage(item.Links[0].Uri" instead of "Avatar = new BitmapImage(item.Links[1].Uri)") - its my guss ;)
  13. 1/9/2010 3:21 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Once I set up the value converter, Visual Studio fails to recognize InitializeComponent, SearchTerm, and SearchResults. Specifically, with

    Error 1 The name 'InitializeComponent' does not exist in the current context C:\Users\Darren\Documents\Visual Studio 2008\Projects\TwitterSearchMonitor\TwitterSearchMonitor\Views\Search.xaml.cs 35 13 TwitterSearchMonitor

    Then my BusyIndicator assignments throw errors too:
    Error 4 An object reference is required for the non-static field, method, or property 'System.Windows.Controls.BusyIndicator.IsBusy.get' C:\Users\Darren\Documents\Visual Studio 2008\Projects\TwitterSearchMonitor\TwitterSearchMonitor\Views\Search.xaml.cs 83 17 TwitterSearchMonitor

    And finally, the search xaml file can't seem to locate TwitterSearchMonitor.Converters, even though I have the line
    xmlns:converters="clr-namespace:TwitterSearchMonitor.Converters"
    within my Search.xaml navigation:Page properties, and an exact copy of your DateTimeConverter.cs class with identical folder structure. Any idea why the compiler seems to miss the code that is clearly there?

    I uploaded my Search.xaml, Search.xaml.cs, and TwitterSearchMonitor.csproj files if you want to take a look at them
    www.mediafire.com/
  14. 1/9/2010 7:47 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Figured out my issue. Sometime in the course of coding, I must have deleted the inital x:Class="TwitterSearchMonitor.Views.Search" from the first line of my Search.xaml. I put that back in and it's working now. :)
  15. 1/13/2010 10:23 AM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    I did not get the avatar to show up either. My path to the avatar is correct, I am also able to cut and paste the path directly onto IE and view the image. I tried resizing the image control and making the background transparent. no luck.
  16. 1/15/2010 6:24 PM | # Getting started with Silverlight:
    Thanks for the tuts...i was stuck at this part yesterday ! Now i am done :)
  17. 1/17/2010 4:34 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Hi Tim, Good tutorial.
    What are the question marks in DateTime? bindingDate = value as DateTime?;
    If you could point me in the right direction, i'd be grateful.
    Thanks
    Christian
  18. 1/18/2010 3:36 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Great tutorial: Ditto Christian on question marks in DateTime?
    Project works great!
  19. 1/18/2010 3:47 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    Reply to DateTime? The question mark allows nullable so you can use .HasValue.
    In VB we have Dim bindDate as Nullable(Of DateTime) but I like the ? better.
  20. Gravatar
    1/31/2010 10:40 PM | # re: Getting started with Silverlight: Part 4 – Binding the data and storing some for later
    I ran your code in VS 2010 Beta 2 and did not see the avator either. Like others said the links to the images are correct. Can you explain? Thanks.
  21. 2/3/2010 1:15 AM | # play video clip using silverlight
    plz,tell me how to play video clip in asp.net using silverlight?

 
Please add 6 and 1 and type the answer here:
First time here? You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting! (hide this)