C# WPF 4:PropertyChanged未更新绑定

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

在我的ViewModel中,我有一个类“a”,其子属性“B”也是一个自定义类。这两个类都实现INotifyPropertyChanged,并且B的PropertyChanged事件连接到激发A的PropertyChanged事件(正确的属性名称为“B”)

我的ViewModel上还有一个DependencyProperty“DPB”,它在代码中通过一个非常简单的绑定(新绑定(“a.B”))绑定到B

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

  • 1受A.B.C.约束(B的财产)
  • 1直接绑定到A.B
  • 1绑定到DPB
第一次运行时,A.B和DPB文本框都显示正确的值。但是当我更改A.B.C文本框时,只有A.B文本框被更新-DPB文本框没有更新

我已经调试了所有PropertyChanged通知代码,它们都被传递了正确的值

问题似乎在于,当触发PropertyChanged事件时,DependencyProperty(或其绑定)没有被更新。有人能告诉我为什么或者如何改变这种行为吗


谢谢。我有个坏消息要告诉你

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