是什么触发了DependencyProperties中的更改通知

本文关键字:通知 DependencyProperties 是什么 | 更新日期: 2023-09-27 18:14:46

我正在研究c#中的数据绑定,并想了解对属性(由依赖属性支持)的哪种更改实际上会触发对绑定目标的更新通知。

对于测试,我使用一个简单的类设置,我可以测试嵌套属性(子属性)的变化:

// Person with a name
public class Person
{
    public String Name { get; set; }
}
// Class giving the best friend as DependencyProperty
public class Friends : DependencyObject
{
    public static DependencyProperty BestFriendProperty =
        DependencyProperty.Register("BestFriend", typeof(Person), typeof(Friends));
    public Person BestFriend
    {
        get { return (Person)this.GetValue(BestFriendProperty); }
        set { this.SetValue(BestFriendProperty, value); }        
    }
}

现在我将BestFriendProperty(作为源)绑定到另一个类的Person属性。我期望通过这个绑定的更新通知只有在我使用BestFriend:

的setter时才有效。
myBoundFriends.BestFriend = new Person(); // myBoundFriends is of type Friends

但是我发现,即使直接更改(嵌套的)Name属性也会触发通知并同步到绑定的目标:

myBoundFriends.BestFriend.Name = "Otto"; // why does this trigger update?

数据绑定对我来说似乎有些神秘。实际上,我认为只有可冻结的对象(在WPF中广泛使用)能够在其任何子属性发生变化时触发更新?!


编辑:当我向绑定添加一个简单的Person to Person转换器时,通知机制按预期工作:

public class PersonPersonConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Person p = (Person)value;
        return new Person(String.Copy(p.Name));
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Person p = (Person)value;
        return new Person(String.Copy(p.Name));
    }
}

注意,转换器通过复制Name字符串对Person对象进行深度复制。我想这可能是一个相关的解决方案

是什么触发了DependencyProperties中的更改通知

这是你的问题,你的数据模型没有实现INotifyPropertyChanged接口。

public class Person
{
    public String Name { get; set; }
}

改为

public class Person : INotifyPropertyChanged
{
    private string name;
    public String Name
    {
        get { return name; }
        set
        {
            if (value == name) return;
            name = value;
            OnPropertyChanged();
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    [NotifyPropertyChangedInvocator] // Comment out this attribute if you don't have R#
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

这将通知GUI在代码中更改绑定到Name属性的任何内容时重新绘制。或者,您可以使用DO作为基类,并使Name属性成为DP,但这只是多余的。我通常有一个基类来实现我的视图模型和数据模型的接口。

是的,我是一个瘾君子;)