×

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!

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


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


7/30/2008 5:10 PM | # re: Silverlight data binding and value converters
Great post; concise, useful. We should do a video on this.
7/31/2008 3:26 PM | # re: Silverlight data binding and value converters
I would make one tweak to your code. The syntax in XAML is little clunking since you have to escape the curly braces. All the parameter to be specified as just a single format specifier. The converter code would detect if there are no curly braces in the specifier and add the appropriate syntax. The end result would be that you can specify the format in a simple way:

Text="{Binding PublishDate, Converter={StaticResource FormatConverter}, ConverterParameter=D}"

or you can do something complicated:

<TextBox.Text>
<Binding Path="PublishDate" Converter="{StaticResource FormatConverter}" ConverterParameter="The {0:d} of {0:MMMM} in the year {0:yyyy}" />
</TextBox.Text>

(I hope I got all of the syntax of that last one correctly)
11/7/2008 8:17 AM | # Silverlight data binding and value converters
i tried implementing this Formater/Copnverter to DatePicker control which was binded to data from a class. When data was puled from the database into the class ....it does not format it as anticipated.
Though this work with other binded controls such as TextBlock ...but not with DatePicker .....below is the code



Any help is appreciated.
Regards
Ambresh
1/20/2009 12:38 PM | # re: Silverlight data binding and value converters
Rob Cannon:

<TextBox.Text>
<Binding Path="PublishDate" Converter="{StaticResource FormatConverter}" ConverterParameter="Blah Blah {0:yyyy}" />
</TextBox.Text>

works fine

<TextBox.Text>
<Binding Path="PublishDate" Converter="{StaticResource FormatConverter}" ConverterParameter="{0:yyyy}" />
</TextBox.Text>

does not work because the compiler recognizes { as a special character when it is the first character.

Is there an escape sequence to get around that?
3/17/2009 2:29 PM | # re: Silverlight data binding and value converters
Try giving space in between ConverterParameter=" {0:C}"
3/24/2009 1:34 PM | # re: Silverlight data binding and value converters
Hey Tim,

Great post, excellent help. Too bad the code examples aren't copy-n-paste-able... :(

Have you tried syntaxhighlighter as explained on Scott Hanselman's blog?
Gravatar
8/4/2009 1:06 PM | # re: Silverlight data binding and value converters
HI Tim,
You do your demos principally declaratively in XAML. I find myself often working in dynamically created controls. I have been fighting with databinding in this scenario. So much so that I've given up and populate values manually and have given up on databinding in general. Can you refer me to any good examples of using databinding as it is intended in the cotext of dynamic controls?
10/5/2009 5:34 PM | # re: Silverlight data binding and value converters
Can we use nested converters in silverlight?
11/13/2009 12:11 PM | # re: Silverlight data binding and value converters
Tim, can I pass a binded property as ConverterParameter?
11/17/2009 1:43 PM | # re: Silverlight data binding and value converters
I end up with compliation error(s). Based on the more explicit XAML the following works but obviously doesn't have the formatting parameter. I've worked around this by specifying a default format string in the converter for dates.

<TextBlock
FontSize="10"
Margin="1,0,1,0">
<TextBlock.Text>
<Binding
Path="CreateDate"
Converter="{StaticResource DateTimeFormatter}"
ConverterParameter="{0}" />
</TextBlock.Text>
</TextBlock>

If I then add the ConverterParameter argument VS2008 complains as follows:

3 The given key was not present in the dictionary <filename> Line:1 Column:1

This error results eventhough I selected ConverterParameter as a result of Intellisense.

Note: Using current toolkits (VS2008SP1, Silverlight3, RIA Services, etc. - prior to 2009 PDC release)
12/17/2009 4:04 PM | # re: Silverlight data binding and value converters
Tim, I am looking around trying to figure out how to display a height in inches, but using two combos one for the feet, one for the inches. Can a converter return a array? Or is there another way to handle this?

EX:
FEET Combo Items{ 4, 5, 6, 7 }
INCHES Combo Items {1,2,3,4...12}

Column data: 73 inches
73/12 = 6 with remainder of 1

So I want to bind the 6 to the 1st combo, the 1 to the second. Ideas?
2/11/2010 3:05 AM | # re: Silverlight data binding and value converters
Hi, Tim Thanks.
Really very good post.
Gravatar
1/5/2011 9:00 AM | # re: Silverlight data binding and value converters
Hi , Can i Bind a list Box with DataContext option with the source assigned to the Grid Control which is above the Visual Tree of ListBox?
3/10/2011 10:45 PM | # re: Silverlight data binding and value converters
Thanks.. Good tips. It is very helpful to me. :)
Gravatar
7/25/2013 3:06 AM | # re: Silverlight data binding and value converters
Thanks. You saved my time.
2/26/2014 2:46 PM | # re: Silverlight data binding and value converters
And if I have Sales.IDVendor, but I want display Vendors.FirstName + ' ' + Vendors.LastName??
I mean, I have the ID in Sales table, but your name is in Vendors table, if my DataGrid is about Sales table, can I add a column with the Vendor's name if this is in Vendors table?

 
Please add 5 and 6 and type the answer here:

DISCLAIMER:

The opinions/content expressed on this blog are provided "ASIS" with no warranties and are my own personal opinions/content (unless otherwise noted) and do not represent my employer's view in any way.