为什么要再次设置此Animatable属性?

时间:2018-12-25 03:47:26

标签: c# wpf xaml dependency-properties dependencyobject

关注this个问题。

显然,出于某种原因,当我设置Parent.Child对象的Child.Trigger属性时,在显式设置Parent.Child属性(在构造函数内部或在构造函数外部)后, ,Parent.Child对象又被设置了。这可以通过中断静态构造函数中定义的_OnChildChanged方法来观察。在调用它的第二个实例上,您可以看到e.OldValue不为空,并且它与e.NewValue相同。

为什么设置Child属性时又要设置Parent的{​​{1}}属性?

符合必要的最低Complete and Verifiable Example

Trigger

要复制:

  1. 创建WPF项目。目标.Net 4.7.2。
  2. 选择using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media.Animation; namespace MCVE { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class Program { [STAThread] public static int Main( ) { Parent p = new Parent( ); p.Child.Trigger = new object( ); return 0; } } public abstract class Base : Animatable { public static readonly DependencyProperty TriggerProperty; static Base( ) => TriggerProperty = DependencyProperty.Register( "Trigger", typeof( object ), typeof( Base) ); public object Trigger { get => this.GetValue( TriggerProperty ); set => this.SetValue( TriggerProperty, value ); } } public class Parent : Base { public static readonly DependencyProperty ChildProperty; static Parent( ) { ChildProperty = DependencyProperty.Register( "Child", typeof( Child ), typeof( Parent ), new PropertyMetadata( null as Child, _OnChildChanged ) ); void _OnChildChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) => Console.WriteLine( "Child Changed!" ); } public Parent( ) : base( ) => this.Child = new Child( ); public Child Child { get => this.GetValue( ChildProperty ) as Child; set => this.SetValue( ChildProperty, value ); } protected override Freezable CreateInstanceCore( ) => new Parent( ); } public class Child : Base { public Child( ) : base( ) { } protected override Freezable CreateInstanceCore( ) => new Child( ); } }
  3. App.xaml下,将Properties更改为Build Action
  4. 将代码粘贴到Page中。覆盖所有内容。

1 个答案:

答案 0 :(得分:1)

我看了 Animatable 类的实现。它是从 freezable 类继承的,而该类又是 DependencyObject 类的继承。

freezable 内部,它重写了 DependencyObject 中的 OnPropertyChanged 事件,并调用所有对Freezable类型的依赖项属性做出响应的处理程序。

这意味着当Child类中的任何依赖项值发生更改时,将调用Freezable类中的 OnPropertyChanged 事件。而且 FireChanged()也已调用。在 FireChange()方法内部,它将调用 GetChangeHandlersAndInvalidateSubProperties 来检查子类中的所有更改,然后只要有任何依赖项,就会调用 _OnChildChanged 属性已更改。

您可以引用Freezable类here的源代码


Freezable Objects OverviewCreating Your Own Freezable Class 部分(重点是我的)中也记录了这种行为:

  

从Freezable派生的类具有以下功能。

     
      
  • 特殊状态:只读(冻结)和可写状态。

  •   
  • 线程安全:冻结的Freezable可以在线程之间共享。

  •   
  • 详细的更改通知:与其他DependencyObjects不同,Freezable对象在子属性值更改时提供更改通知

  •   
  • 轻松克隆:Freezable类已经实现了几种产生深克隆的方法。

  •