我有一个带有DependencyProperty的UserControl。我使用数据绑定表达式在主机窗口中设置它的值。但是,它没有按预期工作。
来自用户控件的代码隐藏的片段:
public class ViewBase : UserControl
{
public static readonly DependencyProperty ViewModelProperty
= DependencyProperty.Register(
"ViewModel", typeof(ViewModelBase), typeof(ViewBase));
public ViewModelBase ViewModel
{
get { return GetValue(ViewModelProperty) as ViewModelBase; }
set
{
SetValue(ViewModelProperty, value);
}
}
}
从XAML(注意:CasingListView继承自ViewBase):
<CasingEditor:CasingListView x:Name="_casingListView"
ViewModel="{Binding CasingListViewModel}" />
什么都没发生。具体来说,永远不会调用setter,并且该属性保持为null。我知道源属性CasingListViewModel
有一个值,因为我试图将它绑定到另一个属性(DataContext),并且它工作正常。
我认为依赖属性可以是数据绑定。我错了吗?
答案 0 :(得分:6)
有时会发生问题,结果却不是我们想象的那样。
我提到从未调用过setter。那是真实的。上面的代码略微修剪,以使其更清晰。不幸的是,在调用SetValue之后,我还在setter中删除了一个语句。该语句将值赋给DataContext,如下所示:
public ViewModelBase ViewModel
{
get { return GetValue(ViewModelProperty) as ViewModelBase; }
set
{
SetValue(ViewModelProperty, value);
DataContext = value;
}
}
正如我现在从this excellent article学到的,当通过数据绑定设置属性时,实际上 setter被绕过。该框架反而直接针对DependencyObject。所以该属性实际上是设置的,但是setter从未被调用过(正如我所提到的),结果是DataContext保持为null并且没有任何效果。
所以:首先,我为提出一个无法回答的问题而道歉。其次,作为弥补它的一种方式,我可以传递非常重要的建议:
永远不要将GetValue()和SetValue()放在属性getter / setter中,因为它们并不总是被调用!
编辑:稍后,我还发现了这种方法的另一个问题。通过这种方式设置DataContext,我实际上首先丢失了支持绑定的原始数据上下文。结果是该属性立即重置为null。总而言之,总的来说这不是一个好方法。