• 星空雅梦


    WPF教程(一) CLR属性和依赖属性

    CLR(Common Language Running)属性,本质是将一个类中的字段进行封装,以达到控制字段获取以及赋值的目的。 如下面的Student类,作为一个学生,年龄显然不能为负数如果想要对age这一字段进行限制,我们可以采用CLR属性进行如下改写。

    1.  
      public class Student
    2.  
      {
    3.  
      public int id;
    4.  
      public string name;
    5.  
      public int age;
    6.  
      }
    1.  
      public class Student
    2.  
      {
    3.  
      public int id;
    4.  
      public string name;
    5.  
      public int ID { get; set; }
    6.  
      public string Name { get; set; }//CLR属性
    7.  
      private int age;
    8.  
      public int Age //CLR属性
    9.  
      {
    10.  
      get { return age; }
    11.  
      set
    12.  
      {
    13.  
      if (value > 0)
    14.  
      {
    15.  
      age = value;
    16.  
      }
    17.  
      }
    18.  
      }
    19.  
      }

    采用CLR属性,可以很方便的控制某一字段的读和写,其本质其实就是类方法,类似于C++中封装的控制类对象成员获取和设置的方法。值得注意的是,WPF的Binding中Path的必须是CLR属性。 

    依赖属性(Dependency Property)的含义是自己没有值,能通过Binding从数据源获得值(依赖在别人身上)的属性,用于依赖属性的对象被称为依赖对象。 

    在传统的.Net开发中,每一个类对象一旦被创建,它的所有字段会被分配了存储空间,以TextBox为例,其包含了138个字段,一旦一个TextBox被创建,其138个字段也就被分配了内存空间,而常用的字段也就Text一个,这就造成了内存空间的浪费。依赖属性的出现,就是为了解决这问题。WPF允许对象在创建时,不包含各个字段所占用的空间,而在使用这个字段时通过其他对象的数据或者实时分配空间,这种对象就是依赖对象,而它这种实时获取数据能力就是依靠依赖属性来实现。 

    WPF中支持依赖对象的类,需要继承自DependevcyObject,依赖属性的类需要继承自DependevcyProperty。DependevcyObject具有GetValue和SetValue两个方法,其都是以DependevcyProperty对象为参数,用于读取和存储依赖属性对象的值。下面我们自已定义一个支持创建依赖对象的类Student,并设置其依赖属性:

    1.  
      public class Student:DependencyObject
    2.  
      {
    3.  
      public static readonly DependencyProperty NameProperty =
    4.  
      DependencyProperty.Register("Name", typeof(string), typeof(Student));
    5.  
       
    6.  
      }

    NameProperty是依赖属性,Name是用于包装NameProperty这个依赖属性的包装器,依赖属性的命名规范是"包装器+Property"。DependencyProperty.Register的三个参数以此是用来存储依赖属性值的CLR属性、该CLR属性的类型、该DependencyObject对象的类型。

    其实从上面的定义我们也可以看出,其实依赖属性的本质就是一个全局的静态的DependencyProperty对象,当我们在开发WPF程序时,系统会准备一个全局的Dictionnary存储了由和“Name”和“Student”类经过某算法生成的唯一键和DependencyProperty的对象组成键值对。而在DependencyObject基类中保存了一个可变的Dictionnary,保存所有和该DependencyObject相关依赖属性的键值以及该属性值,每个DependencyObject对象都有这样一个容器。当使用SetValue对依赖属性进行赋值时,需要先从自带的容器中找到该依赖属性键值,然后 对对应的属性值进行赋值,如果没有就增加一个键值对。当使用GetValue进行依赖属性值的获取时,DependencyObject对象会在其 Dictionnary中进行查找,找到该依赖属性的键值后,返回对应的值,若没找到,返回DependencyProperty对应的默认值(该值在DependencyProperty存储)。 
    另外,至此对于WPF的Bingding也应该具有了一个更深的认识,其需要绑定Target属性就是依赖属性,而这也是依赖属性最主要的使用方面。 对应的XMAL和后台代码:

    1.  
      <Window x:Class="DependencyAttribute.MainWindow"
    2.  
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3.  
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4.  
      Title="MainWindow" Height="350" Width="525">
    5.  
      <Grid>
    6.  
      <TextBox Height="23" HorizontalAlignment="Left" Margin="184,72,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
    7.  
      <TextBox Height="23" HorizontalAlignment="Left" Margin="184,133,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" />
    8.  
      <Button Content="设置和获取依赖属性" Height="23" HorizontalAlignment="Left" Margin="174,208,0,0" Name="button1" VerticalAlignment="Top" Width="162" Click="button1_Click" />
    9.  
      </Grid>
    10.  
      </Window>
    1.  
      private void button1_Click(object sender, RoutedEventArgs e)
    2.  
      {
    3.  
      Student stu = new Student();
    4.  
      stu.SetValue(Student.NameProperty, textBox1.Text);
    5.  
      textBox2.Text = stu.GetValue(Student.NameProperty) as string;
    6.  
      }

    而在通常情况下,我们在使用依赖属性时,都需要用CLR属性将其进行包装,这也是目前所有UI控件对依赖属性的处理方式:

    1.  
      public class Student:DependencyObject
    2.  
      {
    3.  
      public static readonly DependencyProperty NameProperty =
    4.  
      DependencyProperty.Register("Name", typeof(string), typeof(Student));
    5.  
      public string Name
    6.  
      {
    7.  
      get { return (string)GetValue(NameProperty); }
    8.  
      set { SetValue(NameProperty, value); }
    9.  
      }
    10.  
       
    11.  
      }
    1.  
      private void button1_Click(object sender, RoutedEventArgs e)
    2.  
      {
    3.  
      Student stu = new Student();
    4.  
      stu.Name = textBox1.Text;
    5.  
      textBox2.Text = stu.Name;
    6. }

    这样我们就可以利用Student的CLR属性进行数据的绑定,作为Binding的path和目标,且虽然Student没有继承INotifyPropertyChanged接口,在CLR属性的值发生变化时,与之绑定的对象仍然可以得到通知,依赖属性默认带有这样的功能。

  • 相关阅读:
    Backtrader中文笔记之Renko Bricks
    Renko Charts介绍
    Backtrader中文笔记之Cerebro(大脑)。
    Backtrader中文笔记之Operating the platform(操作平台)。
    Backtrader中文笔记之Platform Concepts(平台介绍)。
    Backtrader中文笔记_Quickstart。
    PyAlgoTrade 0.20中文笔记
    浅谈JS中 reduce() 的用法(转帖)
    Python websocket的示例(转帖)
    硬盘显示有容量,但无法放入文件,还有一个查看机器端口是否开放。
  • 原文地址:https://www.cnblogs.com/LiZhongZhongY/p/10870332.html
Copyright © 2020-2023  润新知