C# WPF 4:PropertyChanged未更新绑定
在我的ViewModel中,我有一个类“a”,其子属性“B”也是一个自定义类。这两个类都实现INotifyPropertyChanged,并且B的PropertyChanged事件连接到激发A的PropertyChanged事件(正确的属性名称为“B”) 我的ViewModel上还有一个DependencyProperty“DPB”,它在代码中通过一个非常简单的绑定(新绑定(“a.B”))绑定到B 现在我的视图中有三个文本框:C# WPF 4:PropertyChanged未更新绑定,c#,wpf,binding,C#,Wpf,Binding,在我的ViewModel中,我有一个类“a”,其子属性“B”也是一个自定义类。这两个类都实现INotifyPropertyChanged,并且B的PropertyChanged事件连接到激发A的PropertyChanged事件(正确的属性名称为“B”) 我的ViewModel上还有一个DependencyProperty“DPB”,它在代码中通过一个非常简单的绑定(新绑定(“a.B”))绑定到B 现在我的视图中有三个文本框: 1受A.B.C.约束(B的财产) 1直接绑定到A.B 1绑定到DP
- 1受A.B.C.约束(B的财产)
- 1直接绑定到A.B
- 1绑定到DPB
谢谢。我有个坏消息要告诉你 在
DependencyObject.SetValue中找到检查,检查新值是否等于旧值。因此,如果您绑定到A.B
,并且更改A.B.C
会为A.B
生成PropertyChanged事件,Binding
mechanizm将处理此事件,甚至调用DependencyObject.SetValue
。但是(由于新旧A.B
值相等),DP将不会发生变化
为了实现正确的DP激发,您应该创建新的A.B实例,这将导致非常头痛的结果
已更新
您可以使用Freezable对象,它支持在其属性更改时通知它已更改。DependencyObject可以正确地处理Freezable,所以下一个示例将满足您的需要
模型类:
public class A
{
public A()
{
this.B = new B();
}
public B B
{
get; private set;
}
}
public class B : Freezable, INotifyPropertyChanged
{
protected override Freezable CreateInstanceCore()
{
return new B();
}
private string _c = "initial string";
public string C
{
get
{
return _c;
}
set
{
this._c = value;
this.OnPropertyChanged("C");
this.OnChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
var safe = this.PropertyChanged;
if (safe != null)
{
safe(this, new PropertyChangedEventArgs(name));
}
}
}
Xaml:
<StackPanel>
<TextBox Text="{Binding A.B.C}" />
<TextBox Text="{Binding MyProperty.C}" />
<Button Click="Button_Click"/>
</StackPanel>
您可能需要向绑定中添加Mode=TwoWay
。然而,我不确定我是否正确理解了你的问题,你能添加一些代码吗?如果你构建一点类结构并将其代码粘贴到这里,看起来会更好…嗯,我很害怕。您知道平等性检查是如何执行的吗?如果我重写equals和gethash方法,它会更新吗?equals/gethash方法不会有帮助,因为对象保持不变。事实上我不知道你的目的,也不能给你建议。如果我是你,我会认为这样的麻烦是因为糟糕的设计。您也可以尝试使用Freezable。我已经在我的答案中添加了一些解释代码。谢谢你的帮助,特别是关于Freezable的建议,我现在正在研究。我同意这在某种程度上是一个设计问题,但在设计时B类类型未知的情况下使用它,因此需要中间属性。我感谢您的帮助,并将尽快对此进行标记。在查看Freezable之后,我可以看到它如何可能被使用,但只需要大量开销。但您的回答是正确的,因为DPs不能被强制更新PropertyChanged通知。谢谢
public partial class TextBoxesView : UserControl
{
public TextBoxesView()
{
InitializeComponent();
this.A = new A();
this.DataContext = this;
BindingOperations.SetBinding(this, TextBoxesView.MyPropertyProperty, new Binding("A.B"));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.A.B.C = DateTime.Now.ToString();
}
public A A
{
get;
private set;
}
public B MyProperty
{
get
{
return (B)this.GetValue(TextBoxesView.MyPropertyProperty);
}
set
{
this.SetValue(TextBoxesView.MyPropertyProperty, value);
}
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty",
typeof(B),
typeof(TextBoxesView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, (d, e) => { }));
}