H
H
HitGirl2019-06-04 12:42:15
.NET
HitGirl, 2019-06-04 12:42:15

WPF how do dependency properties (DependencyProperty) work?

Hello!
Let's say I implement a dependency property in a Button-derived class:

using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Petzold.SetSpaceProperty
{
    public class SpaceButton: Button
    {
        string txt;

        public string Text
        {
            set
            {
                txt = value;
                Content = SpaceOutText(txt);
            }
            get
            {
                return txt;
            }
        }

        public static readonly DependencyProperty SpaceProperty;

        public int Space
        {
            set
            {
                SetValue(SpaceProperty, value);
            }
            get
            {
                return (int)GetValue(SpaceProperty);
            }
        }

        static SpaceButton()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = 1;
            metadata.AffectsMeasure = true;
            metadata.Inherits = true;
            metadata.PropertyChangedCallback += OnSpacePropertyChanged;

            SpaceProperty = DependencyProperty.Register("Space", typeof(int), typeof(SpaceButton), metadata, ValidateSpaceValue);
        }

        private static bool ValidateSpaceValue(object obj)
        {
            int i = (int)obj;
            return i >= 0;
        }

        private static void OnSpacePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            SpaceButton btn = obj as SpaceButton;
            btn.Content = btn.SpaceOutText(btn.Text);
        }

        private object SpaceOutText(string str)
        {
            if (str == null)
                return null;

            StringBuilder build = new StringBuilder();
            foreach (char ch in str)
                build.Append(ch + new string(' ', Space));

            return build.ToString();
        }
    }
}

Then I add a new owner to the Window-derived class:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Petzold.SetSpaceProperty
{
    public class SpaceWindow: Window
    {
        public static readonly DependencyProperty SpaceProperty;
        public int Space
        {
            set
            {
                //SetValue(SpaceProperty, value);
                SetValue(SpaceButton.SpaceProperty, value);
            }
            get
            {
                //return (int)GetValue(SpaceProperty);
                return (int)GetValue(SpaceButton.SpaceProperty);
            }
        }

        static SpaceWindow()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata() { Inherits = true};

            SpaceProperty = SpaceButton.SpaceProperty.AddOwner(typeof(SpaceWindow));
            SpaceProperty.OverrideMetadata(typeof(SpaceWindow), metadata);       
        }
    }
}

Can you please tell me why the following code is allowed in the SpaceWindow class: although this property (SpaceProperty) has already been redefined in this class? What is the difference between and ?
SetValue(SpaceButton.SpaceProperty, value);
SetValue(SpaceButton.SpaceProperty, value);SetValue(SpaceProperty, value);
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Petzold.SetSpaceProperty
{
    public class SetSpaceProperty : SpaceWindow
    {
        [STAThread]
        public static void Main()
        {
            Application app = new Application();
            app.Run(new SetSpaceProperty());
        }
        public SetSpaceProperty()
        {
            Title = "Set space property";
            SizeToContent = SizeToContent.WidthAndHeight;
            ResizeMode = ResizeMode.CanMinimize;
            int[] iSpaces = { 0, 1, 2 };

            Grid grid = new Grid();
            Content = grid;

            for(int i = 0; i < 2; ++i)
            {
                RowDefinition row = new RowDefinition() { Height = GridLength.Auto };
                grid.RowDefinitions.Add(row);
            }
            for(int i = 0; i < iSpaces.Length; ++i)
            {
                ColumnDefinition col = new ColumnDefinition() { Width = GridLength.Auto};
                grid.ColumnDefinitions.Add(col);
            }
            for(int i = 0; i < iSpaces.Length; ++i)
            {
                SpaceButton btn = new SpaceButton() { Text = "Set window Space to "+iSpaces[i], Tag = iSpaces[i], HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center};
                btn.Click += WindowPropertyOnClick;
                grid.Children.Add(btn);
                Grid.SetRow(btn, 0);
                Grid.SetColumn(btn, i);

                btn = new SpaceButton() { Text = "Set button Space to " + iSpaces[i], Tag = iSpaces[i], HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
                btn.Click += ButtonPropertyOnClick;
                grid.Children.Add(btn);
                Grid.SetRow(btn, 1);
                Grid.SetColumn(btn, i);
            }
        }

        private void ButtonPropertyOnClick(object sender, RoutedEventArgs args)
        {
            SpaceButton btn = args.Source as SpaceButton;
            btn.Space = (int)btn.Tag;
        }

        private void WindowPropertyOnClick(object sender, RoutedEventArgs args)
        {
            SpaceButton btn = args.Source as SpaceButton;
            Space = (int)btn.Tag;
        }
    }
}

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question