Click here to Skip to main content
15,867,895 members
Articles / Desktop Programming / WPF
Alternative
Article

Bindable Converter and Converter Parameter Revisited

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
9 Sep 2013CPOL 9.1K   8  
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:

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

The Markup extension becomes:

C#
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:

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader ECOMAL Europe GmbH
Germany Germany
I'm 38 and IT Manager at ECOMAL Europe GmbH

Comments and Discussions

 
-- There are no messages in this forum --