| Comments

If you are working with Silverlight and data you most likely are going to leverage data binding at some point and run into some needs to format the data in the XAML.  Luckily this can be done using value converters, which have been available for WPF since it’s inception as well.  Let’s explore what I’m talking about using a common formatting need: dates.

Consider this list box output binding:

   1: <ListBox x:Name="FeedList">
   2:     <ListBox.ItemTemplate>
   3:         <DataTemplate>
   4:             <StackPanel Orientation="Vertical">
   5:                 <TextBlock FontFamily="Arial" FontWeight="Bold" Foreground="Red" Text="{Binding Title.Text}" />
   6:                 <TextBlock FontFamily="Arial" Text="{Binding PublishDate}" />
   7:             </StackPanel>
   8:         </DataTemplate>
   9:     </ListBox.ItemTemplate>
  10: </ListBox>

Assume this XAML binds to SyndicationFeed.Items data coming from an RSS feed.  If we simply bind it the result would be this:

Maybe we don’t want our date to be formatted in such ‘system’ looking format and we want something like “July 16.”  Enter the IValueConverter class.  First we’ll add a class to our Silverlight application, let’s call it Formatter.  Once we add that class we need to implement the IValueConverter interface which gives us Convert and ConvertBack functions we have to implement:

   1: public class Formatter : IValueConverter
   2: {
   3:     #region IValueConverter Members
   4:  
   5:     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   6:     {
   7:         throw new NotImplementedException();
   8:     }
   9:  
  10:     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  11:     {
  12:         throw new NotImplementedException();
  13:     }
  14:  
  15:     #endregion
  16: }

You can see that the Convert function gets some good information that we can use to do the conversion.  The parameter value is the formatter passed into the argument.  For example in our desire to display “July 16” we want to use the date formatter shortcut of “M” for the parameter.  Let’s start the conversion.

   1: public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   2: {
   3:     if (parameter != null)
   4:     {
   5:         string formatterString = parameter.ToString();
   6:  
   7:         if (!string.IsNullOrEmpty(formatterString))
   8:         {
   9:             return string.Format(culture, formatterString, value);
  10:         }
  11:     }
  12:  
  13:     return value.ToString();
  14: }

What we are doing here is ensuring that a parameter is passed in and then using the String object to handle the formatting for us.  Great, now we have our Convert function (in this sample we are doing one-way binding so I’m going to leave ConvertBack alone for now).  Let’s compile our code and then move back to the XAML.  In XAML we now want to make our converter available for use.  The first step is to add the CLR namespace to our root XAML node:

   1: xmlns:converter="clr-namespace:TypeConverter_CS"

The next step is to add our converter class as a resource to our XAML control so that we can use it throughout the control later:

   1: <UserControl.Resources>
   2:     <converter:Formatter x:Key="FormatConverter" />
   3: </UserControl.Resources>

Now if we go back to our XAML where we are data binding the date we can implement this and pass in the converter parameter (format) we want to use.  The end result full XAML looks like this:

   1: <UserControl x:Class="TypeConverter_CS.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:converter="clr-namespace:TypeConverter_CS"
   5:     Width="400" Height="300">
   6:     <UserControl.Resources>
   7:         <converter:Formatter x:Key="FormatConverter" />
   8:     </UserControl.Resources>
   9:     <Grid x:Name="LayoutRoot" Background="White">
  10:         <ListBox x:Name="FeedList">
  11:             <ListBox.ItemTemplate>
  12:                 <DataTemplate>
  13:                     <StackPanel Orientation="Vertical">
  14:                         <TextBlock FontFamily="Arial" FontWeight="Bold" Foreground="Red" Text="{Binding Title.Text}" />
  15:                         <TextBlock FontFamily="Arial" Text="{Binding PublishDate, Converter={StaticResource FormatConverter}, ConverterParameter=\{0:M\}}" />
  16:                     </StackPanel>
  17:                 </DataTemplate>
  18:             </ListBox.ItemTemplate>
  19:         </ListBox>
  20:     </Grid>
  21: </UserControl>

Notice how we made a reference to our StaticResource (using the key name we provided) and then passed in the ConverterParameter of {0:M} to format our date.  The resulting output is now:

And you’ll notice the date formatting.  Now in our converter we could have been real explicit in our Convert function and looked for a date and converted it specifically, but our converter code is generic enough that it can handle some other input types like more complex date formats or numbers.  If we used this same converter code on a number we could pass in the ConverterParameter of {0:c} for currency formatted information.

If you use Expression Blend as well, you can also use some of the user interface properties to specify the binding values that will get output as XAML…here’s a screenshot of the converter settings UI in blend:

This method is useful when you may have custom conversion needs for your data.  Hope this helps!  You can download this sample here: TypeConverter_CS.zip

Please enjoy some of these other recent posts...

Comments