C# 子对象属性更改触发父依赖属性更改回调?

C# 子对象属性更改触发父依赖属性更改回调?,c#,wpf,xaml,dependency-properties,dependencyobject,C#,Wpf,Xaml,Dependency Properties,Dependencyobject,在定义继承可设置动画的类的基类时,我发现了一些奇怪的行为 当我在“Parent”类中创建子DependencyProperty,然后定义该“Parent”类的实例,然后更改parents子类的属性时,我为parents子属性定义的PropertyChangedCallback将触发 符合必要的 使用系统; 使用System.Collections.Generic; 使用System.Windows; 使用System.Windows.Media.Animation; 名称空间MCVE{ ///

在定义继承可设置动画的类的基类时,我发现了一些奇怪的行为

当我在“Parent”类中创建子DependencyProperty,然后定义该“Parent”类的实例,然后更改parents子类的属性时,我为parents子属性定义的PropertyChangedCallback将触发

符合必要的

使用系统;
使用System.Collections.Generic;
使用System.Windows;
使用System.Windows.Media.Animation;
名称空间MCVE{
/// 
///App.xaml的交互逻辑
/// 
公共部分课程{
[状态线程]
公共静态int Main(){
父级p=新父级();
p、 Trigger=newobject();
返回0;
}
}
公共抽象类基:可设置动画{
公共静态只读DependencyProperty触发器属性;
静态基()=>
TriggerProperty=DependencyProperty.Register(
“触发器”、类型(对象)、类型(基础);
公共对象触发器{
get=>this.GetValue(TriggerProperty);
set=>this.SetValue(TriggerProperty,value);
}
}
公共类父级:基{
公共静态只读从属属性ChildProperty;
静态父对象(){
ChildProperty=DependencyProperty.Register(
“儿童”,类型(儿童),类型(父母),
新的PropertyMetadata(作为子项为空,_OnChildChanged));
一经更改无效(
DependencyObject发送方,
DependencyPropertyChangedEventArgs e)=>
Console.WriteLine(“孩子变了!”);
}
公共父级():基()=>
this.Child=newchild();
公共儿童{
get=>this.GetValue(ChildProperty)作为子对象;
set=>this.SetValue(ChildProperty,value);
}
受保护的覆盖Freezable CreateInstanceCore()=>new Parent();
}
公共类子类:基{
公共子级():基(){}
受保护的重写Freezable CreateInstanceCore()=>新子级();
}
}
复制:

  • 创建WPF项目。目标.Net 4.7.2
  • 选择
    App.xaml
  • 属性
    下,将
    生成操作
    更改为
    页面
  • 将代码粘贴到
    App.xaml.cs
    中。覆盖所有内容
  • 运行此代码时,您应该会在控制台中看到消息print两次

    为什么会这样?有没有办法阻止它发生


    后续操作:

    在控制台中打印消息2次,因为子属性设置了2次:

    • 第一次在父构造函数中(this.Child=new Child();)
    • 第二次调用p.Child.Trigger=newobject()
    我认为在您的情况下,您可以在_OnChildChanged()中比较子属性的新值和旧值,以防止出现问题:

                void _OnChildChanged(
                    DependencyObject sender,
                    DependencyPropertyChangedEventArgs e)
                {
                    if (e.NewValue != e.OldValue)
                    {
                        Console.WriteLine("Child Changed!");
                    }
                }
    

    问候

    您好,我尝试运行您的代码,它抛出System.TypeInitializationException异常,如下代码行:“ChildProperty=DependencyProperty.Register(“Child”、typeof(Child)、typeof(Parent)、new PropertyMetadata(作为子级为null,_OnChildChanged));”@NhanPhan您是将项目创建为控制台应用程序还是WPF应用程序。它需要是一个WPF应用程序。请注意,将
    null作为子项写入
    是多余的,原因有两个。首先,
    null
    可分配给每个引用类型,其次,PropertyMetadata构造函数的默认值参数的类型是
    object
    @Clemens,这是公平的。这只是我个人的偏好,因为我有一些用于注册依赖属性的实用方法,一个需要
    default
    值,一个需要
    PropertyMetaData
    ,因此如果我没有通过
    null作为Foo
    显式提供属性类型,它会感到不安。太好了。那么,为什么在没有显式设置属性的情况下第二次设置属性呢?我想这需要进入一个新的问题。。。
                void _OnChildChanged(
                    DependencyObject sender,
                    DependencyPropertyChangedEventArgs e)
                {
                    if (e.NewValue != e.OldValue)
                    {
                        Console.WriteLine("Child Changed!");
                    }
                }