WPF之依赖属性的继承

为依赖属性增加属性值继承的特性

通常我们会给某一个控件(元素)添加依赖属性,如果希望这个依赖属性的改变可以影响到当前窗体中所有拥有此属性的元素,那么就需要属性值得继承特性;

思路如下:
有如下自定义按钮类:

public class SpaceButton : Button
    {
        // 传统.Net做法 私有字段搭配一个公开属性
        string txt;

        public string Text
        {
            set
            {
                txt = value;
                Content = SpaceOutText(txt);
            }
            get
            {
                return txt;
            }
        }
        // 依赖属性
        public static readonly DependencyProperty SpaceProperty;

        //.Net属性包装器
        public int Space
        {
            set
            {
                SetValue(SpaceProperty, value);
            }
            get
            {
                return (int)GetValue(SpaceProperty);
            }
        }

        // 静态的构造函数
        static SpaceButton()
        {
            // 定义元数据
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = 0;
            metadata.Inherits = true;
            metadata.PropertyChangedCallback += OnSpacePropertyChanged;

            // 注册依赖属性
            SpaceProperty = DependencyProperty.Register("Space", typeof(int), typeof(SpaceButton), metadata, ValidateSpaceValue);
        }

        // 值验证的回调函数
        static bool ValidateSpaceValue(object obj)
        {
            int i = (int)obj;
            return i >= 0;
        }

        // 属性值改变的回调函数
        static void OnSpacePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            SpaceButton btn = obj as SpaceButton;
            string txt = btn.Content as string;
            if (txt == null) return;
            btn.Content = btn.SpaceOutText(txt);
        }

        // 该方法给字符串间距加上空格
        string SpaceOutText(string str)
        {
            if (str == null)
                return null;

            StringBuilder build = new StringBuilder();

            // 往里面加上Space个空格
            foreach (char ch in str)
                build.Append(ch + new string(' ', Space));

            return build.ToString();
        }
    }

可以看到代码中有一个Space的自定义依赖属性,用于控制文本之间的间距,当前情况下是没有进行属性继承的方式,此时使用方式如下:

<local:SpaceButton x:Name="btnSpace" Grid.Column="0" Grid.Row="0" Margin="5" Click="btnSpace_Click" Text="设置按钮字符空格:2">
  private void btnSpace_Click(object sender, RoutedEventArgs e)
        {
            this.btnSpace.Space = 2;
        }

看起来没什么不一样,就是一般的依赖属性的使用,接下来开始修改代码,使代码可以达到值继承的效果。
首先,在窗体中添加Space属性

static MainWindow()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
            metadata.Inherits = true;
            SpaceProperty = SpaceButton.SpaceProperty.AddOwner(typeof(MainWindow));
            SpaceProperty.OverrideMetadata(typeof(Window),metadata);
        }

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

可以看到,代码和SpaceButton中有些差别,这里的依赖属性Space不是注册而来,而是从SpaceButton的Space属性的AddOwner方法而来。即依赖属性可以选择把自身添加给其他属性,这是普通属性无法实现的。另外注意一点,要设置元数据(FraeworkPropertyMetadata)的Inherits属性为true,才可以实现属性值继承,同时也要修改SpaceButton中元数据的Inhertis属性也为true。
Xaml使用方法如下:

<Window x:Class="mumu_Button02.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local ="clr-namespace:mumu_Button02"
        Title="mumu_Button02" Width="300" Height="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <local:SpaceButton x:Name="btnSpace" Grid.Column="0" Grid.Row="0" Margin="5" Click="btnSpace_Click" Text="设置按钮字符空格:2">
        </local:SpaceButton>
        <local:SpaceButton x:Name= "winSpace" Grid.Column="0" Grid.Row="1" Margin="5" Click="winSpace_Click" Text="设置窗口字符空格:2">

        </local:SpaceButton>
    </Grid>

</Window>

窗体中有两个按钮,分别控制当前按钮和窗体的字符之间的空格;

        private void btnSpace_Click(object sender, RoutedEventArgs e)
        {
            this.btnSpace.Space = 2;
        }

        private void winSpace_Click(object sender, RoutedEventArgs e)
        {
            this.Space = 2;
        }

这时候当按下 ”设置窗体字符空格“的按钮,则会修改两个按钮的字符空格,而另一个按钮则只能控制自己的字符空格。

 

posted @ 2013-05-11 18:19  wangyafei_it  阅读(518)  评论(0编辑  收藏  举报