问题描述
关注问题。
显然,出于某种原因,在显式设置了 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( );
}
}
要重现:
- 创建WPF项目。目标.Net 4.7.2。
- 选择
App.xaml
- <$ c以下$ c>属性,将
构建操作
更改为页面
- 将代码粘贴到
App.xaml.cs
中。覆盖所有内容。
- Create WPF Project. Target .Net 4.7.2.
- Select
App.xaml
- Under
Properties
, changeBuild Action
toPage
- 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属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!