Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the Source value in ConvertBack() method for IValueConverter implementation in WPF binding

I am binding a dependency property to textboxex in WPF. The property is a string that has some values separated by '/' (example: "1/2/3/4" ). I need to bind individual values to separate textboxes which is fine with following implementation of Convert() method:

public object Convert(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture)
{
  if (!string.IsNullOrEmpty(value as string))
  {
    String[] data = (value as string).Split('/');
    return data[Int16.Parse(parameter as string)];
  }
  return String.Empty;
}

And I am using the ConverterParameter in xaml to specify the position of wanted value. However, the problem is with ConvertBack() method. I do not know, how to get the source value so I could just add or change just one value in the string (on the specified position).

Thanks for any help.

like image 553
tom Avatar asked Aug 15 '11 11:08

tom


2 Answers

Update

You have probably solved your issue already with the help of Vlad, I just thought I should add another way of actually getting the source value in the converter.

First you could make your converter derive from DependencyObject so you can add a Dependency Property to it which we shall bind to

public class MyConverter : DependencyObject, IValueConverter
{
    public static DependencyProperty SourceValueProperty =
        DependencyProperty.Register("SourceValue",
                                    typeof(string),
                                    typeof(MyConverter));
    public string SourceValue
    {
        get { return (string)GetValue(SourceValueProperty); }
        set { SetValue(SourceValueProperty, value); }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        //...
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        object targetValue = value;
        object sourceValue = SourceValue;
        //...
    }
}

Unfortunately, a Converter doesn't have a DataContext so the Binding won't work out of the box but you can use Josh Smith's excellent DataContextSpy: Artificial Inheritance Contexts in WPF

<TextBox>
    <TextBox.Resources>
        <src:DataContextSpy x:Key="dataContextSpy" />
    </TextBox.Resources>
    <TextBox.Text>
        <Binding Path="YourProperty"
                 ConverterParameter="1">
            <Binding.Converter>
                <src:MyConverter SourceValue="{Binding Source={StaticResource dataContextSpy},
                                                       Path=DataContext.YourProperty}"/>
            </Binding.Converter>
        </Binding>
    </TextBox.Text>
</TextBox>

End of Update

Dr.WPF has an elegant solution to this, see the following thread
The way to access binding source in ConvertBack()?

Edit

Using the solution by Dr.WPF, you could supply both the string index and the source TextBox to the converter with this (perhaps a little verbose) sample code

<TextBox dw:ObjectReference.Declaration="{dw:ObjectReference textBoxSource}">
    <TextBox.Text>
        <Binding Path="YourStringProperty"
                 Converter="{StaticResource YourConverter}">
            <Binding.ConverterParameter>
                <x:Array Type="sys:Object">
                    <sys:Int16>1</sys:Int16>
                    <dw:ObjectReference Key="textBoxSource"/>
                </x:Array>
            </Binding.ConverterParameter>
        </Binding>
    </TextBox.Text>
</TextBox>

And then you could later access both the index and the TextBox in the ConvertBack method

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    object[] parameters = parameter as object[];
    short index = (short)parameters[0];
    object source = (parameters[1] as TextBox).DataContext;
    //...
}
like image 155
Fredrik Hedblad Avatar answered Sep 22 '22 19:09

Fredrik Hedblad


In most cases, you can safely make ConvertBack just throw NotImplementedException.

Indeed, you just haven't got enough information to recreate the source value from its part!

If you really need the back conversion (e.g., if you use two-direction binding), I would split the property into 3 strings in the view model (the class used in DataContext), and bind to them separately.

like image 43
Vlad Avatar answered Sep 22 '22 19:09

Vlad