避免“无法创建默认转换器以在类型‘Derived_N’和‘Base’之间执行‘双向’转换”错误的解决方法

Den*_*nis 5 c# wpf

我有一些类型层次结构:

public class Base {}
public class Derived_1 : Base {}
public class Derived_2 : Base {}
// more descendants...
public class Derived_N : Base {}
Run Code Online (Sandbox Code Playgroud)

此层次结构中的类型用作视图模型中的查找列表:

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
}
Run Code Online (Sandbox Code Playgroud)

为了从查找列表中选择值,我创建了用户控件(某种选择器)。由于从选择过程的角度来看,所有Base后代看起来都相似,因此用户控件操作Base类型属性:

    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));
Run Code Online (Sandbox Code Playgroud)

XAML 通常看起来像:

<myCtrls:BaseSelector ItemsSource="{Binding SomeItems}"
                      SelectedItem="{Binding SelectedItem}"/>
Run Code Online (Sandbox Code Playgroud)

这按预期工作,但存在如下绑定错误:

无法创建默认转换器以在类型“Derived_N”和“Base”之间执行“双向”转换

我知道,为什么它们在输出窗口中 - 理论上,SelectedItem可以是任何类型,派生自Base,但实际上这不是我的情况。如果此转换器:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

用于绑定:

<myCtrls:BaseSelector ItemsSource="{Binding SomeItems}"
                      SelectedItem="{Binding SelectedItem, Converter={StaticResource DummyConverterKey}}"/>
Run Code Online (Sandbox Code Playgroud)

但我根本不想使用它 - 如您所见,该转换器中没有任何有效负载(虽然有很多这样的属性)。

还有其他解决方法吗?

Den*_*nis 3

现在,我已经解决了将用户控件的属性的属性类型分别替换为IEnumerable/的问题objectIEnumerable<object>/object也是一个解决方案):

    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));
Run Code Online (Sandbox Code Playgroud)

这会导致用户控件内部进行额外的类型检查,但不会生成任何绑定错误(我真的不明白,为什么 - with 的情况与objectwith 相同Base,IMO)。