Le FormatConverter, et les XamlParseException dans Microsoft Expression Blend

Un converter que l’on voit et réimplémente très souvent est le FormatConverter, qui consiste à prendre en entrée une chaîne et l’utiliser comme paramètre pour la méthode String.Format. Cela permet par exemple d’éviter une redondance de runs lorsque l’on souhaite concaténer des chaînes, ou encore d’appliquer un formatage spécifique aux flottants ou aux dates.

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

    if (value == null) return null;

    var parm = parameter as string;

    if (string.IsNullOrEmpty(parm)) return value;

    return string.Format(parm, value);

}

 

Ce qui donne à l’utilisation :

{Binding MyValue, Converter={StaticResource BlendableFormatConverter}, ConverterParameter='{0:0.00} €'}

Notons que l’on échappe ici la chaîne à traiter par des apostrophes, et que l’on doit utiliser la notation {0} pour spécifier l’emplacement de la valeur du binding à formater.

L’implémentation naturelle de ce converter a un inconvénient majeur : les accolades étant normalement réservées aux markup extensions XAML, elles provoquent des erreurs de syntaxe/parsing avec  WPF et Expression Blend. Le parser de Silverlight 3 étant plus permissif, le converter compile et fonctionne au runtime pour les applications RIA, mais cause toujours une XamlParseException dans Expression Blend.

image

La solution de contournement est simple : remplacer les accolades par des crochets dans le XAML, puis effectuer la substitution inverse dans le converter :

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

{

    if (value == null) return null;

    var parm = parameter as string;

    if (string.IsNullOrEmpty(parm)) return value;

    return string.Format(parm.Replace('[','{').Replace(']','}'), value);

}

Ce qui donne à l’utilisation :

{Binding MyValue, Converter={StaticResource BlendableFormatConverter}, ConverterParameter='[0:0.00] €'}

Cette astuce très simple fonctionne sur les deux plateformes et permet, au grand bonheur du designer/intégrateur XAML, d’obtenir un rendu visuel interactif directement dans Expression Blend.

BlendableFormatConverterDemo.zip