避免“无法创建默认转换器以在类型'Derived_N'和'基本'之间执行'双向'转换”错误的解决方法
本文关键字:之间 基本 执行 双向 解决 方法 错误 转换 Derived 创建 默认 | 更新日期: 2023-09-27 18:33:35
我有一些类型层次结构:
public class Base {}
public class Derived_1 : Base {}
public class Derived_2 : Base {}
// more descendants...
public class Derived_N : Base {}
此层次结构中的类型用作视图模型中的查找列表:
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
}
为了从查找列表中选择值,我创建了用户控件(某种选择器(。由于从选择过程的角度来看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));
XAML 通常如下所示:
<myCtrls:BaseSelector ItemsSource="{Binding SomeItems}"
SelectedItem="{Binding SelectedItem}"/>
这按预期工作,但存在如下绑定错误:
无法创建默认转换器来执行"双向"转换 在类型"Derived_N"和"基本"之间
我知道,为什么它们在输出窗口中 - 理论上,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;
}
}
用于绑定:
<myCtrls:BaseSelector ItemsSource="{Binding SomeItems}"
SelectedItem="{Binding SelectedItem, Converter={StaticResource DummyConverterKey}}"/>
但我根本不想使用它 - 如您所见,该转换器中没有任何有效载荷(虽然有很多这样的属性(。
还有其他解决方法吗?
现在,我已经解决了将用户控件的属性类型分别替换为 IEnumerable
/object
的问题(IEnumerable<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));
这会导致用户控件内部的额外类型检查,但不会产生任何绑定错误(我真的不明白,为什么 - object
的情况与 Base
IMO 的情况相同(。
将TypeConverter与类一起使用以避免此错误:
[TypeConverter(typeof(MyConverter))]
public class Derived_N : Base
{
}
类型转换器:
public class MyConverter: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context,
Type sourceType)
{
return sourceType == typeof(Base);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
return value as Base;
}
public override bool CanConvertTo(ITypeDescriptorContext context,
Type destinationType)
{
return destinationType == typeof(Base);
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value, Type destinationType)
{
return value == null ? null : value as Base;
}
}
PS:请根据需要更改上面的代码。我只是写了最小的以防止错误。