问题描述
我用通用集合依赖属性创建了自定义控件。 但是,只要从xaml更改了此属性,setter的视图模型中的值就为空。
CustomControl:
public IList A
{
get { return (IList)GetValue(AProperty); }
set { SetValue(AProperty,value); }
}
public static readonly DependencyProperty AProperty =
DependencyProperty.Register(nameof(A),typeof(IList),typeof(CustomControl),new PropertyMetadata(new List<object>()));
viewmodel:
List<B> collectionB;
public List<B> CollectionB
{
get { return collectionB; }
set
{
if (collectionB == value) return;
collectionB = value;
}
}
如果我将CollectionB的类型更改为List
解决方法
集合属性的最通用类型是IEnumerable
-例如,参见ItemsControl.ItemsSource
属性。
还要注意,为集合类型依赖项属性设置非空默认值是有问题的,因为拥有类的所有实例默认情况下都将在同一集合实例上运行。将一个元素添加到一个控件的A属性将更改所有其他控件实例的集合。
您应该这样声明属性:
public IEnumerable A
{
get { return (IEnumerable)GetValue(AProperty); }
set { SetValue(AProperty,value); }
}
public static readonly DependencyProperty AProperty =
DependencyProperty.Register(
nameof(A),typeof(IEnumerable),typeof(CustomControl));
如果您确实需要一个非空的默认值,请将其添加到控件的构造函数中:
SetCurrentValue(AProperty,new List<object>());
更新:对集合类型属性使用OneWayToSource
绑定
<local:CustomControl A="{Binding CollectionB,Mode=OneWayToSource}" />
仅在A
的默认值与绑定的source属性赋值兼容时有效,该属性不适用于List<object>
和List<B>
。
您应该根本不设置默认值,而应使用TwoWay绑定
<local:CustomControl A="{Binding CollectionB,Mode=TwoWay}" />
使用
private List<B> collectionB = new List<B>();
public List<B> CollectionB
{
get { return collectionB; }
set { collectionB = value; }
}
或者只是
public List<B> CollectionB { get; set; } = new List<B>();
,
这是因为IList<T>
没有实现IList
,所以从一种类型转换为另一种类型将失败。
如果您想与A
绑定,则必须将其绑定到也正在实现IList
的东西上