Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Bindable Converter and Converter Parameter Revisited

0.00/5 (No votes)
9 Sep 2013 1  
This is an alternative for Bindable Converter Parameter

Introduction

The article http://www.codeproject.com/Articles/459958/Bindable-Converter-and-Converter-Parameter written by saved my day.

I just wanted to contribute making the code more robust....

Using the code

This is the usage in the XAML:

<TextBox 
                                               
Text="{myNameSpace:BindableConverter
                                          
Binding={Binding Path=...},
ConverterBinding={Binding Path=...},
UpdateSourceTrigger=PropertyChanged}" />

The Markup extension becomes:

public class BindableConverter : MarkupExtension
{
    public Binding Binding { get; set; }
    public IValueConverter Converter { get; set; }
    public Binding ConverterBinding { get; set; }
    public object ConverterParameter { get; set; }
    public Binding ConverterParameterBinding { get; set; }
    public UpdateSourceTrigger UpdateSourceTrigger { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (Converter == null && ConverterBinding == null)
            throw new Exception("Neither Converter nor ConverterBinding where provided");

        if (ConverterBinding == null && ConverterParameterBinding == null)
            throw new Exception("There is no point using this Extension. Please use standard Binding");

        MultiBinding multiBinding = new MultiBinding();
        multiBinding.UpdateSourceTrigger = UpdateSourceTrigger;
        multiBinding.Bindings.Add(Binding);
        if (ConverterBinding != null)
            multiBinding.Bindings.Add(ConverterBinding);
        if (ConverterParameterBinding != null)
            multiBinding.Bindings.Add(ConverterParameterBinding);

        BindableConverterAdapter adapter = new BindableConverterAdapter();
        adapter.Converter = Converter;
        adapter.ConverterParameter = ConverterParameter;

        multiBinding.Converter = adapter;
        return multiBinding.ProvideValue(serviceProvider);
    }
}

And the Adapter becomes:

public class BindableConverterAdapter : IMultiValueConverter
{
    public IValueConverter Converter { get; set; }
    public object ConverterParameter { get; set; }

    #region IMultiValueConverter Members

    /// <summary>
    /// ConverterBinding and ConverterParameterBinding take
    /// precedence over respectively Converter and ConverterParameter
    /// </summary>
    <returns>public object Convert(object[] values, Type targetType, 
                   object parameter, CultureInfo culture)
    {
        //values [0]: Binding
        //values [1]: IValueConverter or BindingParameter
        //values [2]: only BindingParameter

        IValueConverter converterBinding = values[1] as IValueConverter;
        if (converterBinding != null)
        {
            Converter = converterBinding;
            if (values.Length > 2)
                ConverterParameter = values[2];
        }
        else
            ConverterParameter = values[1];

        return Converter.Convert(values[0], targetType, ConverterParameter, culture);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, 
                  object parameter, CultureInfo culture)
    {
        return new[] {Converter.ConvertBack(value, targetTypes[0], null, culture)};
    }

    #endregion
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here