Child object property change fires parents Depende

2019-06-11 01:01发布

In defining a base class inheriting an the Animatable, class, I have discovered what I am finding to be some odd behavior.

When I create a Child DependencyProperty within a 'Parent' class, then define an instance of that 'Parent' class, then alter a property on the parents child, the PropertyChangedCallback I defined for the Parents Child property fires.

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

To reproduce:

  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.

Running this code, you should see the message print twice within the console.

Why is this happening? Is there a way to STOP it from happening?

Follow Up Here:

1条回答
Emotional °昔
2楼-- · 2019-06-11 01:41

The message print 2 times in console because Child property was set 2 times:

  • 1st time in Parent constructor( this.Child = new Child( );)
  • 2nd time when you call p.Child.Trigger = new object( );

I think in your case, you can compare new value and old value of Child property in _OnChildChanged() to prevent the problem:

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

Regards!

查看更多
登录 后发表回答