2011-04-05 122 views
3

在我的ViewModel中,我有一个类“A”与子属性“B”,也是一个自定义类。这两个类实现INotifyPropertyChanged并且B的PropertyChanged事件被连接到触发A的PropertyChanged事件(具有正确的属性名称“B”)。WPF 4:PropertyChanged没有更新绑定

我的ViewModel上还有一个DependencyProperty“DPB”,该代码绑定了B,代码中使用了一个非常简单的绑定(new Binding(“A.B”))。

现在我在我的视图中的三个文本框:

  • 1绑定到ABC(B的一个属性)
  • 1直接键合于AB
  • 1绑定到DPB

首次运行时,AB和DPB文本框都显示正确的值。但是,当我更改A.B.C文本框时,只有A.B文本框被更新 - DPB文本框未更新。

我已通过所有PropertyChanged通知代码进行调试,并且它们全部都是通过正确的值传递的。

问题似乎是在激发PropertyChanged事件时,DependencyProperty(或它的绑定)没有被更新。任何人都可以告诉我为什么或者如何改变这种行为?

谢谢。

+0

您可能需要一个'模式= TwoWay'添加到绑定。但是,我不确定我是否正确理解了你的问题,你可以添加一些代码吗? – Damascus 2011-04-05 12:53:20

+1

如果您稍微创建类结构并在此处粘贴它的代码,看起来好多了... – 2011-04-05 12:53:24

回答

3

我对你有坏消息。

里面DependencyObject.SetValue检查位于,检查是否新值等于旧值。因此,如果您绑定到A.B,并且更改A.B.C会产生PropertyChanged事件A.B,Binding mechanizm将处理此事件,甚至会呼叫DependencyObject.SetValue。但之后(由于旧的和新的A.B值相等)没有更改将应用​​于DP。

为了实现正确的DP启动,您应该创建一个新的A.B实例,最终令人头痛。

修订

你可以使用可冻结对象,它支持通知,当它的属性改变它已经改变了。 DependencyObject正确地与Freezables一起工作,所以下一个例子就是你所需要的。

模型类:

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> 

后面的代码:

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) => { })); 
} 
+0

嗯,我很害怕这个。你知道如何检查平等吗?如果我重写equals和gethash方法,它会更新吗? – 2011-04-05 14:10:41

+1

Equals/GetHash方法将不起作用,因为对象保持不变。其实我不知道你的目的,我不能告诉你。如果我是你,我会认为这样的麻烦是由于糟糕的设计而发生的。你也可以尝试使用Freezable。我已经为我的答案添加了一些解释代码。 – 2011-04-05 16:04:57

+0

感谢您的帮助,特别是对于Freezable的建议,我正在研究这个。我同意这是一个设计问题,但它在设计时不知道B类类型的地方使用,因此需要中间属性。我感谢你的帮助,并很快就会回答这个问题。 – 2011-04-05 16:26:27

相关问题