| Comments

One thing that I’m just as guilty as probably most of some of my peers is creating US-centric applications.  Forgetting to think globally for your users is something that I think happens too often.  We operate in our US-centric worlds and forget that sometimes even the simplest things can make a difference.

Take for instance, honoring your user’s culture settings (region/locale/whatever you want to call it).  Even if you have a US-based application for a US-company, how do you know that a user might not be of French origin and still perhaps like to view their operating system information in French settings, so they change their culture.

Luckily in some areas this is simple to do, and for Silverlight applications you can let the platform do some of the work for you.  I’ll take a simple example of currency settings.  A colleague of mine was asking about currency formatting in his Silverlight application with regard to data binding.  He sent me a note asking why his formatter didn’t work.  He asked me why:

   1: ConverterParameter={0:$##.00}

As it turns out, it was just something missing in his implementing of a custom converter in his application.  But I let him know that he should really use {0:c} and let the platform do the work.  Let’s look at a simple example of an employee and their salary.  If we data bind this information to a DataGrid using the above formatter here is what we might get:

Makes sense right, looks fine.  Now let’s change the regional settings on my machine to French (France):

Hmm…what happened here.  Well the problem is we forced the format.  Let’s change the format parameter to {0:c} and keep French as our settings and see:

Ah, now that makes sense.  You see we can let our platform do the work and Silverlight is aware of how to use culture settings to honor currency, dates, etc. – here’s the default Calendar with French settings:

Now ideally in our sample with salaries above a literal visual translation probably isn’t accurate (by that I mean USD $1 is not the same as 1 Euro right now in translation.  We could add some custom logic though and get this output based on culture settings:

So be mindful of your applications and look for ways you can reliably and meaningfully add value to your global end users.  Don’t force a format unless you absolutely have to.

| 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