Martijn's blog - E-Commerce, EAI, BizTalk and .NET

2006/10/15

WPF - Writing an IMultiValueConverter

Currently, I'm working on a project involving WPF. I will post my experiences from time to time. This week, I wrote a simple IMultiValueConverter implementation which can be used to format a set of bindings in a String.Format fashion. This is how it works:

Define the class and assign a key to refer to it:
<Window.Resources>
  <c:StringFormatterConverter
      x:Key="StringFormatterConverter" />
</Window.Resources>

Bind some element (GridViewColumn in this case) to a datasource, in this case something which has properties called LASTNAME and FIRSTNAME on it:
<GridViewColumn.DisplayMemberBinding>
 <MultiBinding>
   <Binding Path="LASTNAME" />
   <Binding Path="FIRSTNAME" />
 </MultiBinding>
</GridViewColumn.DisplayMemberBinding>

Now set a converter on the MultiBinding:
<MultiBinding Converter="{StaticResource StringFormatterConverter}" ConverterParameter="{}{0}, {1}">

Both IValueConverter and IMultiValueConverter implement two methods:

  • Convert
  • ConvertBack
One for binding one direction and the other for the opposite direction (from->to).

The ConverterParameter in the Converter is used to pass the format we'll be using to display the bound elements.
Let's look at a code sample (sanity checks are removed for readability purposes):
public class StringFormatterConverter : IMultiValueConverter
{
 public object Convert(
  object[] values,
  Type targetType,
  object parameter,
  System.Globalization.CultureInfo culture)
 {
  return string.Format(
   culture,
   formatArgument,
   values);

 }

 public object[] ConvertBack(
  object value,
  Type[] targetTypes,
  object parameter,
  System.Globalization.CultureInfo culture)
 {
  throw new NotImplementedException(
   "Unable to convert a formatted argument string back.");
 }
}

It's that simple, WPF will pass the values to the converter and expects a converted value back. We format the values using the other supplied arguments, parameter ('{0}, {1}') and culture.

You can use any string.Format argument you'd like; just remember to escape the first '{' sign, so the Xaml interpreter knows you don't mean to use a Markup Extension.

Escaping the first brace is done by placing an empty mark extension in front of
the character ('{}{').

The namespace prefix 'c' refers to the assembly and namespace implementing the converter (e.g. <xmlns:c="clr-namespace:Martijn.Wpf.Converters" />

2 Comments:

  • Interesting post. Now of course, converting the formatted data back would be the great challenge (enabling editing). I understand that it is by definition impossible to do it 'always right', but maybe it would be possible to have a 'good for most practical cases' version.

    It would involve parsing out the placeholders, looking up the literals in the passed object, figuring out the string values for the separate values and then redoing the conversion to see if it gives the same result. Would be a lot of work though.

    By Anonymous Anonymous, at 9:17 AM  

  • You Wrote "Escaping the first brace is done by placing an empty mark extension in front of
    the character ('{}{'). "

    Thanks so much this was driving me nuts couldn't figure out why I had to have a literal as first character...

    By Anonymous Anonymous, at 3:59 PM  

Post a Comment

<< Home