ValueConverter with multiple arguments

3.5k views Asked by At

I'm trying to write a control that has three related properties: value, minimum and maximum. Value changes, but minimum and maximum are fixed.

So I wrote a IMultiValueConverter:

public class AngleMultiConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double value = (double)values[0];
        double minimum = (double)values[1];
        double maximum = (double)values[2];

        double angle = -150.0 + ((value - minimum) * 300.0 / (maximum - minimum));
        return angle;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The XAML looks like the following (it's a custom control, hence the RelativeSource stuff):

<RotateTransform.Angle>
    <MultiBinding Converter="{StaticResource angleMultiConverter}">
        <Binding Path="Value" RelativeSource="{RelativeSource AncestorType={x:Type local:KnobControl}}"/>
        <Binding Path="MinimumValue" RelativeSource="{RelativeSource AncestorType={x:Type local:KnobControl}}" Mode="OneWay"/>
        <Binding Path="MaximumValue" RelativeSource="{RelativeSource AncestorType={x:Type local:KnobControl}}" Mode="OneWay"/>
    </MultiBinding>
</RotateTransform.Angle>

That works fine, but what about ConvertBack? I have to pass back three values... but I only have one? The other two are constants, so how do I know what they are?

My other solution that works is to create a dependancy property called Angle which does all the work in a custom control... but exposes Angle which seems wrong.

2

There are 2 answers

0
imekon On BEST ANSWER

The only answer I've found is create a property called Angle and let that do the work, as I originally pointed out in my question, and bonyjoe concluded.

9
ndonohoe On

If your Min and Max values never change then you can just have them as properties on the Converter and use a normal IValueConverter to do the conversion, then you are only binding a single value.

You can pass values to the converter at creation time like so

<UserControl.Resources>
    <utils:AngleConverter Min="20" Max="2000" x:Key="angleConverter"/>
</UserControl.Resources>

If you want to bind these properties it may be possible to use DependencyObject as the base class for the converter and create Min and Max as dependency properties instead of standard properties, though I have never tried this

Custom Control Implementation

In constructor

this.Resources.Add("AngleConverter", new AngleConverter() { Min = _min, Max = _max });

In Min/Max value changed

((AngleConverter)this.Resources["AngleConverter"]).Min = newMin;
((AngleConverter)this.Resources["AngleConverter"]).Max = newMax;