我想创建一个UserControl,用户可以在其中绑定多种类型的数据。通常我定义一个依赖属性,例如:
public ObservableCollection<MyDataType1> Values
{
get { return (ObservableCollection<MyDataType1>)GetValue(ValuesProperty); }
set { SetValue(ValuesProperty, value); }
}
public static readonly DependencyProperty ValuesProperty =
DependencyProperty.Register(
"Values", typeof(ObservableCollection<MyDataType1>),
typeof(MyUserControl),
new PropertyMetadata(
null));
如何将某种类型的强制转换定义为MyDataType1?
示例:
public class MyDataType1
{
string ID { get; set; }
string Title { get; set; }
SolidColorBrush Color { get; set; }
}
我希望也可以绑定:
ObservableCollection<int> TestCollection { get; set; }
我试图在MyDataType1中定义一个隐式转换:
static public implicit operator MyDataType1(int value)
{
return new MyDataType1()
{
ID = value,
Color = Colors.Black,
Title = "Not defined"
};
}
然而,当我用int整理集合时,我的控件并没有显示任何内容。
<ItemsControl ItemsSource="{Binding Values}" ItemTemplate="{StaticResource MyTemplate}" />
要实现这一目标,我 想要定义Converter
。
答案 0 :(得分:2)
对象属性的绑定在运行时得到解决,这意味着你几乎可以在XAML中转储任何绑定,如果绑定不起作用,它就会忽略它。
使用此功能,可以有效地选择您将要使用的数据类型。我想说实现这一目标的最佳方法是使用interface
。这是一个例子:
public interface IAwesome
{
int ID { get; }
}
public class MegaClass : IAwesome
{
public int ID { get; set; }
...
}
public class SuperClass : IAwesome
{
public int ID { get; set; }
...
}
使用此方法,您的依赖项属性将如下所示:
public ObservableCollection<IAwesome> Values
{
get { return (ObservableCollection<IAwesome>)GetValue(ValuesProperty); }
set { SetValue(ValuesProperty, value); }
}
public static readonly DependencyProperty ValuesProperty =
DependencyProperty.Register(
"Values", typeof(ObservableCollection<IAwesome>),
typeof(MyUserControl),
new PropertyMetadata(
null));
另外需要提及的是,您还可以使用键入的DataTemplate
,请参阅此处:
<DataTemplate DataType="{x:Type MyNamespace:SomethingOrOther}">
这样您就可以为特定DataTemplate
定义Type
,因此即使您的收藏集是IAwesome
的列表,它们也可能会在容器中以不同的方式显示已分配DataTemplate
。
这样做的好处是你的强类型C#仍然有效,但在你的场景中,我们需要使这甚至更多通用。
使用interface
的方法并没有真正解决您的问题,因为int
无法从IAwesome
继承,所以如果您尝试,您将会遇到编译器错误将任何int
值分配给此属性。解决这个问题的方法是使用object
。
public ObservableCollection<object> Values
{
get { return (ObservableCollection<object>)GetValue(ValuesProperty); }
set { SetValue(ValuesProperty, value); }
}
public static readonly DependencyProperty ValuesProperty =
DependencyProperty.Register(
"Values", typeof(ObservableCollection<object>),
typeof(MyUserControl),
new PropertyMetadata(
null));
由于所有都继承自object
,因此您可以将任意值添加到此集合中。
在你真正需要在C#中使用这个属性之前,这一切都很好。你会遇到很多麻烦,因为你需要强制这些对象到他们想要的类型。
在您不需要使用这些值的情况下,这应该足够了,否则,您可能需要重新考虑您的控件,也许它正在尝试太多事情。
答案 1 :(得分:1)
ObservableCollection不是一个好主意。尝试访问一个尝试返回从依赖项属性获取的值的属性(比如在运行时将ObservableCollection绑定到它),并使用强制转换为ObservableCollection。它将炸弹。这是因为您的自定义数据类型不是从对象继承的。它违反了称为“协方差”的规则。我试过这种方法并走到了尽头。接口是唯一的出路。也许是动态物体。