本文介绍了为什么要再次设置此Animatable属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关注问题。

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

Apparently, for some reason after having explicitly set the Parent.Child property ( either inside the constructor or explicitly outside of the constructor ), when I set the Child.Trigger property of the Parent.Child object, the Parent.Child object is being set yet again. This can be observed by breaking on the _OnChildChanged method defined within the static constructor. On the second instance of it being called, you can see that e.OldValue is not null, and that it is the same as e.NewValue.

为什么是父级的 Child 属性 Trigger 属性时是否再次设置code>?

WHY is the Child property of Parent being set yet again when setting the Trigger property?

要符合必要的最低要求, :

In compliance with the requisite Minimal, Complete and Verifiable Example:

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( );
    }
}

要重现:


  1. 创建WPF项目。目标.Net 4.7.2。

  2. 选择 App.xaml

  3. <$ c以下$ c>属性,将构建操作更改为页面

  4. 将代码粘贴到 App.xaml.cs 中。覆盖所有内容。

  1. Create WPF Project. Target .Net 4.7.2.
  2. Select App.xaml
  3. Under Properties, change Build Action to Page
  4. Paste code into App.xaml.cs. Overwrite EVERYTHING.


推荐答案

我介绍了 Animatable 的实现方式强>类。它继承自 freezable 类,而该类又继承自 DependencyObject 类。

I took a look on implementation of the Animatable class. It is inherited from freezable class which is inherited from DependencyObject class.

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

Inside freezable, it overwrote OnPropertyChanged event from the DependencyObject and invoke all handlers which is response to a changing dependency property of type Freezable.

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

That mean when any dependency value in Child class has changed, OnPropertyChanged event in Freezable class will be called. And the FireChanged() has called also. Inside FireChange() method, it will call GetChangeHandlersAndInvalidateSubProperties to check all changed from sub class, and then the _OnChildChanged will be invoked whenever any its dependency property has changed.

您可以引用Freezable类

You can refer source code of Freezable class here

此行为也记录在,第(强调我的):

This behavior is also documented in Freezable Objects Overview, section Creating Your Own Freezable Class (emphasis mine):

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


  • 特殊状态:只读-(冻结)且处于可写状态。

  • Special states: a read-only (frozen) and a writable state.

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

Thread safety: a frozen Freezable can be shared across threads.

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

Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

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

Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

这篇关于为什么要再次设置此Animatable属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-21 07:36