Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Workaround to avoid "Cannot create default converter to perform 'two-way' conversions between types 'Derived_N' and 'Base'" error

Tags:

c#

wpf

I have some types hierarchy:

public class Base {}
public class Derived_1 : Base {}
public class Derived_2 : Base {}
// more descendants...
public class Derived_N : Base {}

Types from this hierarchy are used as lookup lists in view models:

public class SomeViewModel
{
    // available items
    public IEnumerable<Derived_N> SomeItems { get; }

    // currently selected item
    public Derived_N SelectedItem { get; set; }

    // there could be several property pairs as above
}

To select values from lookup list I've created user control (some sort of selector). Since from the point of selection process all Base descendants looks similar, user control operates Base type properties:

    public IEnumerable<Base> ItemsSource
    {
        get { return (IEnumerable<Base>)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable<Base>), typeof(BaseSelector), new PropertyMetadata(null));

    public Base SelectedItem
    {
        get { return (Base)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(Base), typeof(BaseSelector), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

XAML usually looks like:

<myCtrls:BaseSelector ItemsSource="{Binding SomeItems}"
                      SelectedItem="{Binding SelectedItem}"/>

This works as expected, but there are binding errors like this:

Cannot create default converter to perform 'two-way' conversions between types 'Derived_N' and 'Base'

I know, why they are in output window - in theory, SelectedItem could be any type, derived from Base, but in practice this is not my case. The error disappears, if this converter:

public class DummyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

is used in binding:

<myCtrls:BaseSelector ItemsSource="{Binding SomeItems}"
                      SelectedItem="{Binding SelectedItem, Converter={StaticResource DummyConverterKey}}"/>

but I don't want to use it at all - as you can see, there are no any payload in that converter (while there are lot such of properties).

Are there any other workaround?

like image 291
Dennis Avatar asked Sep 26 '22 10:09

Dennis


1 Answers

For now, I've solved a problem with replacing property type for user control's properties to IEnumerable / object respectively (IEnumerable<object> / object is also a solution):

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(BaseSelector), new PropertyMetadata(null));

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(BaseSelector), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

This leads to extra type checking inside user control, but doesn't generate any binding errors (and I really don't understand, why - the case with object is the same as with Base, IMO).

like image 165
Dennis Avatar answered Sep 28 '22 04:09

Dennis