Почему это свойство Animatable устанавливается снова? - PullRequest
0 голосов
/ 25 декабря 2018

Следуйте до этого вопроса.

По-видимому, по какой-то причине после явного задания свойства Parent.Child (либо внутри конструктора, либо явно вне конструктора), когда яустановите свойство Child.Trigger объекта Parent.Child, объект Parent.Child устанавливается снова.Это можно наблюдать, нарушая метод _OnChildChanged, определенный в статическом конструкторе.Во втором случае его вызова вы можете видеть, что e.OldValue не равно нулю и что оно совпадает с e.NewValue.

WHY - это свойство Child устанавливаемой Parentеще раз при установке свойства Trigger?

В соответствии с обязательным минимальным, Полный и проверяемый пример :

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.Target .Net 4.7.2.
  2. Выберите App.xaml
  3. Под Properties, измените Build Action на Page
  4. Вставьте код в App.xaml.cs.Перезаписать ВСЕ.

1 Ответ

0 голосов
/ 25 декабря 2018

Я посмотрел на реализацию класса Animatable .Он наследуется от freezable класса, который наследуется от DependencyObject class.

Внутри freezable , он перезаписал OnPropertyChanged событиеиз DependencyObject и вызывает все обработчики, которые являются ответом на изменяющееся свойство зависимости типа Freezable.

Это означает, что при изменении любого значения зависимости в дочернем классе, OnPropertyChanged будет вызвано событие в классе Freezable.И FireChanged () также вызывает .Внутри метода FireChange () он будет вызывать GetChangeHandlersAndInvalidateSubProperties , чтобы проверить все изменения из подкласса, а затем _OnChildChanged будет вызываться всякий раз, когда изменяется любое его свойство зависимости.

Вы можете ссылаться на исходный код класса Freezable здесь


Это поведение также задокументировано в Обзор замораживаемых объектов , раздел Создание собственного класса Freezable (выделено мной):

Класс, производный от Freezable, получает следующие функции.

  • Особые состояния: aтолько для чтения (заморожено) и состояние записи.

  • Безопасность потоков: замороженная Freezable может быть разделена между потоками.

  • Подробное уведомление об изменении: В отличие от других объектов DependencyObject, объекты Freezable предоставляют уведомления об изменении при изменении значений под-свойств .

  • Простое клонирование: класс Freezable ужеРеализовано несколько методов получения глубоких клонов.

...