Une contrainte à laquelle on fait face rapidement lors de l'utilisation de ValueConverters est celle qui force l'attribut ConverterParameter à être statique. Il n'est en effet pas possible de binder l'attribut ConverterParameter à une DependencyProperty, ce qui restraint énormément son usage. Ce post décrit une technique de contournement, voici son fonctionnement :
Dans le projet exemple, PaddingConverter peut être configuré par ses deux propriétés IsLeftPadding et TargetLength.
Ces deux propriétés sont modifiables par le biais respectivement d’une CheckBox et d’un Slider :
<CheckBox IsChecked="{Binding Source={StaticResource PaddingConverter},Path=IsLeftPadding}" …>
<Slider Value="{Binding Source={StaticResource PaddingConverter},Path=TargetLength}"…>
Le changement de valeur de ces propriétés ne peut cependant pas déclencher une mise à jour automatique de l’affichage car c’est toujours le Binding qui appelle le ValueConverter, et non le contraire.
On arrive ainsi à la partie la moins élégante de cette technique : il faut déclencher une réévaluation du Binding dans le code-behind dès qu’une propriété du ValueConverter change. Pour cela, PaddingConverter implémente l’interface INotifyPropertyChanged, et son parent (la fenêtre) s’abonne à l’évènement PropertyChanged du ValueConverter pour exécuter la méthode un BindingExpression.UpdateTarget() sur les éléments utilisant le PaddingConverter (le TextBlock dans notre cas).
var converter = this.FindResource("PaddingConverter") as PaddingConverter;
converter.PropertyChanged += new PropertyChangedEventHandler(
delegate(Object o, PropertyChangedEventArgs ea)
{
if (txt == null)
return; // Il faut mettre à jour les endroits où le converter est utilisé BindingExpression be = txt.GetBindingExpression(TextBlock.TextProperty); be.UpdateTarget(); });
En espérant que cette technique vous dépannera, rendez-vous au prochain post !