WPF: Get the source value in ConvertBack() method

The other day I needed the source value in the ConvertBack() method of a converter class. Unfortunately the arguments do not provide this value.
My first try was to bind the value as a ConvertParameter, without success. The next idea was to use a DependancyProperty with the Converter. But the Converter is not an element of the element tree, so it has no DataContext. At codeproject I found a great article that shows a little helper class which observers the element tree and provides the DataContext to elements outside of the element tree.

Converter class with DependancyProperty:

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

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        String sourceValue = SourceValue;

        return value;
    }
}

DataContextSpy class from codeproject:

public class DataContextSpy : Freezable
{
    public DataContextSpy()
    {
        BindingOperations.SetBinding(this, DataContextProperty, new Binding());

        this.IsSynchronizedWithCurrentItem = true;
    }

    public bool IsSynchronizedWithCurrentItem { get; set; }

    public object DataContext
    {
        get { return (object)GetValue(DataContextProperty); }
        set { SetValue(DataContextProperty, value); }
    }

    public static readonly DependencyProperty DataContextProperty =
        FrameworkElement.DataContextProperty.AddOwner(
        typeof(DataContextSpy),
        new PropertyMetadata(null, null, OnCoerceDataContext));

    static object OnCoerceDataContext(DependencyObject depObj, object value)
    {
        DataContextSpy spy = depObj as DataContextSpy;
        if (spy == null)
            return value;

        if (spy.IsSynchronizedWithCurrentItem)
        {
            ICollectionView view = CollectionViewSource.GetDefaultView(value);
            if (view != null)
                return view.CurrentItem;
        }

        return value;
    }

    protected override Freezable CreateInstanceCore()
    {
        throw new NotImplementedException();
    }
}

And the WPF DropBox as an example implementation:

<ComboBox ItemsSource="{Binding Path=Values}"  Height="23"  HorizontalAlignment="Left" Margin="66,12,0,0" VerticalAlignment="Top" Width="120">
    <ComboBox.Resources>
        <l:ValueConverter x:Key="converter" />
        <l:DataContextSpy x:Key="dataContextSpy" />
    </ComboBox.Resources>
        <ComboBox.SelectedValue>
        <Binding Path="BindingValue" Mode="TwoWay">
            <Binding.Converter>
                <l:ValueConverter
                    SourceValue="{Binding Source={StaticResource dataContextSpy}, Path=DataContext.BindingValue}"/>
            </Binding.Converter>
        </Binding>
    </ComboBox.SelectedValue>
</ComboBox>

The full project with all sources can be found on github.

Advertisements
This entry was posted in C#, Development, WPF and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s