WPF-属性系统

CLR属性

什么是CLR属性

.Net中的属性称为CLR属性

新建Student类,添加四个属性(快捷键:输入propfull,按两下Tab):

namespace WpfLearningDemo
{
    class Student2
    {
        private string _name;

        public string MyName
        {
            get { return _name; }
            set { _name = value; }
        }

        private int _age;

        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }

        private string _sex;

        public string Sex
        {
            get { return _sex; }
            set { _sex = value; }
        }

        private string _address;

        public string Address
        {
            get { return _address; }
            set { _address = value; }
        }

    }
}

Name,Age,Sex,Address这四个属性就是CLR属性

CLR属性的作用:

  • 实现封装

  • 加入验证逻辑

    比如:

    private int _age;
    
    public int Age
    {
        get { return _age; }
        set
        {
            if (value > 0 && value < 111)
            {
                _age = value;
            }
        }
    }
    
  • 控制外部代码的访问

    private int _sex;
    
    public int Sex
    {
        get { return _sex; } //只读属性
    }
    

WPF依赖属性

特点

  • 属性变更通知

    如果我们想要实现:当鼠标移到Button上修改其前景色,移出后恢复。

    我们可能需要自己去实现鼠标移入移出的事件:

    
    
    

    cs文件中处理鼠标事件:

    private void Button_MouseEnter(object sender, MouseEventArgs e)
    {
        Button btn = sender as Button;
        if (btn != null)
        {
            btn.Foreground = Brushes.Blue;
        }
    }
    
    private void Button_MouseLeave(object sender, MouseEventArgs e)
    {
        Button btn = sender as Button;
        if (btn != null)
        {
            btn.Foreground = Brushes.Black;
        }
    }
    

    以上可以实现这样的需求。

    但是,我们还可以用Button的依赖属性Foreground来实现,添加一个样式触发器:

    
    

    这样实现了同样的效果,而且不用自己处理鼠标事件。

  • 属性值继承

    我们给UserControl设置一个FontSize属性,然后添加两个TextBlock

    
        
            
                我使用继承的FontSize
                我使用自己的FontSize
            
        
    
    

    显示效果:

  • 节省内存空间

依赖属性的定义

  • 声明依赖属性变量
  • 在属性系统中注册
  • 使用.NET属性包装依赖属性

示例:

新建一个用户控件MyDependencyPropertyUserControl

xaml文件中添加控件:

依赖属性

cs文件中定义自己的依赖属性:

namespace WpfLearningDemo
{
    /// 
    /// MyDependencyProperty.xaml 的交互逻辑
    /// 
    public partial class MyDependencyPropertyUserControl : UserControl
    {
        public MyDependencyPropertyUserControl()
        {
            InitializeComponent();
        }

        // 1.声明依赖属性
        public static readonly DependencyProperty MyColorProperty;

        static MyDependencyPropertyUserControl()
        {
            /// 2.依赖属性注册
            /// 参数:name, propertyType, ownerType, propertyMetaData
            MyColorProperty = DependencyProperty.Register("MyColor", typeof(string), typeof(MyDependencyPropertyUserControl), 
                new PropertyMetadata("Red", (s,e)=> 
                {
                    //元数据逻辑操作
                }));
        }

        /// 3.对依赖属性进行封装
        /// 这里的属性名对应于注册时的"MyColor"
        public string MyColor
        {
            get { return (string)GetValue(MyColorProperty); }
            set { SetValue(MyColorProperty, value); }
        }
    }
}

使用Visual Studio 快捷键添加依赖属性:输入propdp,按两下Tab键。

依赖属性的应用

首先完善我们自定义的依赖属性的注册:

MyColorProperty = DependencyProperty.Register("MyColor", typeof(string), typeof(MyDependencyPropertyUserControl), 
                new PropertyMetadata("Red", (s,e)=> 
                {
                    //元数据逻辑操作
                    var mdp = s as MyDependencyPropertyUserControl;
                    if (mdp != null)
                    {
                        try
                        {
                            var color = (Color)ColorConverter.ConvertFromString(e.NewValue.ToString()); //将数据转换为颜色值
                            mdp.Foreground = new SolidColorBrush(color); //修改前景色
                        }
                        catch (Exception)
                        {
                            mdp.Foreground = new SolidColorBrush(Colors.Black);
                        }
                    }
                }));

MainWindow.xaml中使用:


    
        
        
    

依赖属性MyColor的数据来源绑定为TextBox的输入,根据输入的颜色值,修改MyDependencyPropertyUserControl控件的前景色。

效果:

附加属性

特点

  • 是一个特殊的依赖属性
  • 用于非定义该属性的类

定义

  • 声明附加属性变量
  • 在属性系统中进行注册
  • 调用静态方法设置和获取属性值

快捷键:propa+两下Tab

示例:

MyDependencyPropertyUserControl.xaml.cs文件中添加附加属性MyAttachedFontSize

// 定义静态方法设置和获取附加属性值
public static int GetMyAttachedFontSize(DependencyObject obj)
{
    return (int)obj.GetValue(MyAttachedFontSizeProperty);
}

public static void SetMyAttachedFontSize(DependencyObject obj, int value)
{
    obj.SetValue(MyAttachedFontSizeProperty, value);
}

// 声明和注册附加属性变量
public static readonly DependencyProperty MyAttachedFontSizeProperty =
    DependencyProperty.RegisterAttached("MyAttachedFontSize", typeof(int), typeof(MyDependencyPropertyUserControl), new PropertyMetadata((s, e)=> 
                {
                    // 连续取父级,找到MyDependencyPropertyUserControl
                    var mdp = (((s as FrameworkElement).Parent as FrameworkElement).Parent as FrameworkElement).Parent as MyDependencyPropertyUserControl;
                    if (mdp != null && e.NewValue != null)
                    {
                        var fontSize = 9;
                        int.TryParse(e.NewValue.ToString(), out fontSize);
                        mdp.FontSize = fontSize;
                    }
                }));

修改MyDependencyPropertyUserControl.xaml,添加一个TextBox与附加属性MyAttachedFontSize绑定:


    
        
        通过附加属性FontSize修改字体大小
    

实现效果: