wpf入门教程系列十一——依赖属性

倾城风云 倾城风云     2022-09-20     674

关键词:

一、依赖属性基本介绍

  本篇开始学习WPF的另一个重要内容依赖属性。

     大家都知道WPF带来了很多新的特性,其中一个就是引入了一种新的属性机制——依赖属性。依赖属性出现的目的是用来实现WPF中的样式、自动绑定及实现动画等特性。依赖属性的出现是WPF这种特殊的呈现原理派生出来的,与.NET普通属性不同的是,依赖属性的值是依靠多个提供程序来判断的,并且其具有内建的传递变更通知的能力。

     依赖属性基本应用在了WPF的所有需要设置属性的元素。依赖属性根据多个提供对象来决定它的值 (可以是动画、父类元素、绑定、样式和模板等),同时这个值也能及时响应变化。

     依赖属性就是可以自己没有值,并能够通过Binding从数据源获 取值(依赖在别人身上)的属性。拥有依赖属性的对象被称为“依赖对象”。依赖项属性的重点在于“依赖”二字,既然是依赖了,也就是说:依赖项属性的值的改变过程一定与其它对相关,不A依赖B就B依赖A,或者相互依赖。

 

     说白了,所谓依赖,主要应用在以下地方:

     1、双向绑定。有了这个,依赖项属性不用写额的代码,也不用实现什么接口,它本身就俱备双向绑定的特性,比如,我把员工对象的姓名绑定到摇文本框,一旦绑定,只要文本框中的值发生改变,依赖项属性员工姓名也会跟着变化,反之亦然;

     2、触发器。这个东西在WPF中很重要,比如,一个按钮背景是红色,我想让它在鼠标停留在它上面是背景变成绿色,而鼠标一旦移开,按钮恢复红色。

如果在传统的Windows编程中,你一定会想办法弄一些事件,或者委托来处理,还要写一堆代码。告诉你,有了依赖项属性,你将一行代码都不用写,所有的处理均由WPF属性系统自动处理。而触发器只是临时改变属性的值,当触完成时,属性值自动被“还原”。

     3、附加属性。附加属性也是依赖项属性,它可以把A类型的的某些属性推迟到运行时根据B类型的具体情况来进行设置,而且可以同时被多个类型对象同时维护同一个属性值,但每个实例的属性值是独立的。

     4、A属性改变时,也同时改变其它属性的值,如TogleButton按下的同时,弹出下拉框。

 

     与传统的CLR属性和面向对象相比依赖属性有很多新颖之处,其中包括:

      1、新功能的引入:加入了属性变化通知,限制、验证等等功能,这样就可以使我们更方便的实现我们的应用,同时也使代码量大大减少了,许多之前不可能的功能都可以轻松的实现了。 
      2、 节约内存:在WinForm等项目开发中,你会发现UI控件的属性通常都是赋予的初始值,为每一个属性存储一个字段将是对内存的巨大浪费。WPF依赖属性 允许对象在被创建的时候并不包含用于存储数据的空间(即字段所占用的空间)、只保留在需要用到数据的时候能够获得默认值。借用其它对象的数据或者实 时分配空间的能力----这种对象称为依赖对象而他这种实时获取数据的能力则依靠依赖属性来实现。在WPF开发中,必须使用依赖对象作为依赖属性的宿主, 使二者结合起来,才能形成完整的Binding目标被数据所驱动。。 
      3、支持多个提供对象:我们可以通过多种方式来设置依赖属性的值。同时其内部可以储存多个值,配合Expression、Style、Animation等可以给我们带来很强的开发体验。 
  在.NET当中,对于属性是大家应该很熟悉,封装类的字段,表示类的状态,编译后被转化为对应的get和set方法。属性可以被类或结构等使用。 一个简单的属性如下,也是我们常用的写法:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Student
 
    {
 
        string m_Name;
 
  
 
        public string Name
 
        {
 
            get return m_Name; }
 
            set { m_Name = value; }
 
        }
 
        static Student()
 
        {
 
        
 
        }
 
  
 
  
 
    }

 

     依赖属性与普通的.NET属性的区别是普通的.NET属性定义只需要定义其set和get区块的赋值与设置。那么依赖属性应该怎么定义呢?依赖属性和属性到底有什么区别和联系呢?其实依赖属性的实现也很简单,按以下步骤做就可以了:

     第一步: 让自己的类继承自 DependencyObject基类。在WPF中,几乎所有的UI元素都继承自DependencyObject,这个类封装了对依赖属性的存储及 访问等操作,使用静态类型与依赖属性的内部存储机制相关。WPF处理依赖属性不再像普通.NET属性那样将属性值存储到一个私有变量中,而是使用一个字典 型的变量来存放用户显示设置的值。

     第二步:依赖属性的定义必须使用 public static 声明一个 DependencyProperty的变量,并且有一个Property作为后缀,该变量才是真正的依赖属性 。例如下面的代码定义了一个依赖属性NameProperty:

 

1
public static readonly DependencyProperty NameProperty;

 

     第三步:在静态构造函数中向属性系统注册依赖属性,并获取对象引用。依赖属性是通过调用DependencyProperty.Register静态方法创建,该方法需要传递一个属性 名称,这个名称非常重要,在定义控件Style和Template的时候,Setter的Property属性填入的值就是注册依赖属性时使用的名称。propertyType指明了依赖属性实际的类型,ownerType指明了是哪个类注册了此依赖属性,最后typeMetadata存放了一些依赖属 性的元信息,包括依赖属性使用的默认值,还有属性值发生变更时的通知函数。例如,下面的代码注册了依赖属性。

 

1
NameProperty = DependencyProperty.Register("Name"typeof(string), typeof(Student),  new PropertyMetadata("名称", OnValueChanged));

 

     第四步:在前面的三步中,我们完成了一个依赖属性的注册,那么我们怎样才能对这个依赖属性进行读写呢?答案就是提供一个依赖属性的实例化包装属性,通过这个属性来实现具体的读写操作。和CLR属性不同,依赖属性不是直接对私有变量的操纵,而是通过GetValue()和SetValue()方法来操作属性值的,可以使用标准的.NET属性定义语法进行封装,使依赖属性可以像标准属性那样来使用,代码如下。

1
2
3
4
5
6
7
8
9
public string Name
 
      {
 
          get return (string)GetValue(NameProperty); }
 
          set { SetValue(NameProperty, value); }
 
      }

 

 

根据前面的四步操作,我们就可以写出下面的代码:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class Student : DependencyObject
 
    {
 
        //声明一个静态只读的DependencyProperty字段
 
        public static readonly DependencyProperty NameProperty;
 
  
 
        static Student()
 
        {
 
            //注册我们定义的依赖属性Name
 
            NameProperty = DependencyProperty.Register("Name"typeof(string), typeof(Student),
 
                new PropertyMetadata("名称", OnValueChanged));
 
        }
 
  
 
        private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
 
        {
 
            //当值改变时,我们可以在此做一些逻辑处理
 
        }
 
  
 
        //属性包装器,通过它来读取和设置我们刚才注册的依赖属性
 
        public string Name
 
        {
 
            get return (string)GetValue(NameProperty); }
 
            set { SetValue(NameProperty, value); }
 
        }
 
  
 
}

 

     总结:我们一般.NET属性是直接对类的一个私有属性进行封装,所以读取值的时候,也就是直接读取这个字段;而依赖属性则是通过调用继承自DependencyObject的GetValue()和SetValue来进行操作,它实际存储在DependencyProperty的一个IDictionary的键-值配对字典中,所以一条记录中的键(Key)就是该属性的HashCode值,而值(Value)则是我们注册的DependencyProperty。

wpf入门教程系列十三——依赖属性

四、只读依赖属性  在以前在对于非WPF的功能来说,对于类的属性的封装中,经常会对那些希望暴露给外界只读操作的字段封装成只读属性,同样在WPF中也提供了只读属性的概念,如一些WPF控件的依赖属性是只读的,它们经常... 查看详情

wpf入门教程系列十二——依赖属性

二、依赖属性的优先级  由于WPF允许我们可以在多个地方设置依赖属性的值,所以我们就必须要用一个标准来保证值的优先级别。比如下面的例子中,我们在三个地方设置了按钮的背景颜色,那么哪一个设置才会是最终的结果... 查看详情

wpf入门教程系列二十一——datagrid示例

DataGrid示例的后台代码1) 通过EntityFramework6.1从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,从S_Province表中读取省份信息,然后通过绑定的方式反数据显示到WPF的Window上的一个DataGrid上。具体代码如下。usingSys... 查看详情

wpf学习第十一章理解依赖项属性(代码片段)

  依赖项属性是标准.NET属性的全新实现——具有大量新增价值。在WPF的核心特性(如动画、数据绑定以及样式)中需要嵌入依赖项属性。WPF元素提供的大多数属性都是依赖项属性。到目前位置所见到的所有示例都用到了依... 查看详情

wpf入门教程系列二十一——datagrid示例

 前面我们学习了ListView控件的使用示例,今天我们来学习DataGrid的有关知识。提到DataGrid不管是Asp.Net中的网页开发还是WinForm应用程序开发都会频繁使用。通过它我们可以灵活的在行与列间显示各种数据。本篇将学习WPF中的Data... 查看详情

wpf教程:依赖属性

一、什么是依赖属性依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值。依赖属性可支持WPF中的样式设置、数据绑定、继承、动画及默认值。将所有的属性都设置为依赖属性并不总是正确的解决方案,具... 查看详情

wpf基础教程之属性系统

...服务通常统称为WPF属性系统由WPF属性系统支持的属性称为依赖项属性本概述介绍WPF属性系统以及依赖项属性的功能这包括如何在可扩展应用程序标记语言(XAML)中和代码中使用现有的依赖项属性本概述还介绍了依赖项属性所特有的... 查看详情

WPF:绑定到依赖属性

】WPF:绑定到依赖属性【英文标题】:WPF:bindingtoadependencyproperty【发布时间】:2011-03-0902:53:45【问题描述】:我正在关注here的教程。它显示了一个关于如何绑定到依赖属性的基本示例。<BindingElementName="This"Path="IPAddress"UpdateSource... 查看详情

wpf的依赖属性和附加属性(用法解释较全)(代码片段)

...习写博文了,出于负罪感,今天强烈逼迫自己开始更新WPF系列。尽管最近看到一篇WPF技术是否老矣的文章,但是还是不能阻止我系统学习WPF。今天继续分享WPF中一个最重要的知识点——依赖属性。二、依赖属性的全面解析... 查看详情

wpf入门教程系列二十——listview示例

第四步、WPF后台逻辑代码编写在后台用EntityFramework6.1的CodeFirst方式获取数据库中的数据。同时,在“刷新”按钮的方法中进行数据绑定。操作步骤如下:1) 在“刷新”按钮上使用鼠标右键,单击,会弹出“属性”窗口。如下... 查看详情

wpf入门教程系列九——布局之dockpanel与viewbox

七.DockPanelDockPanel定义一个区域,在此区域中,您可以使子元素通过描点的形式排列,这些对象位于Children属性中。停靠面板其实就是在WinForm类似于Dock属性的元素。DockPanel会对每个子元素进行排序,并停靠在面板的一侧,多个停... 查看详情

wpf入门教程系列十五——wpf中的数据绑定

 使用WindowsPresentationFoundation(WPF)可以很方便的设计出强大的用户界面,同时WPF提供了数据绑定功能。WPF的数据绑定跟Winform与ASP.NET中的数据绑定功能类似,但也有所不同,在WPF中以通过后台代码绑定、前台XAML中进行绑定,或... 查看详情

wpf教程:附加属性

一、附加属性的特点1、特殊的依赖属性2、用于非定义该属性的类例如Grid面板的RowDefinition、ColumnDefinition、Canvas面板的Left、RightDockPanel面板的Dock都是附加属性。二、附加属性的定义1、声明数据属性变量。publicstatic的DependencyPropert... 查看详情

wpf入门教程系列十——布局之border与viewbox

九.BorderBorder是一个装饰的控件,此控件绘制边框及背景,在Border中只能有一个子控件,若要显示多个子控件,需要将一个附加的Panel控件放置在父Border中。然后可以将子控件放置在该Panel控件中。Border的几个重要属性:Background:... 查看详情

wpfstepbystep系列-开篇

WPF系列包含的内容 WPF基础知识介绍WPF布局介绍WPF控件介绍(包含第三方控件)WPF自定义模板WPF依赖属性、路由事件WPF的MVVM编程WPF开发框架PrismWPF开发框架WAFWPF开发框架CaliburnWPF为什么我们选择? 介绍     &n... 查看详情

springboot2系列教程(二十一)|自动配置原理

微信公众号:一个优秀的废人。如有问题,请后台留言,反正我也不会听。前言这个月过去两天了,这篇文章才跟大家见面,最近比较累,大家见谅下。下班后闲着无聊看了下SpringBoot中的自动配置,把我的理解跟大家说下。配... 查看详情

wpf中的依赖属性

#1.WPF中的依赖属性依赖属性是专门基于WPF创建的。在WPF库实现中,依赖属性使用普通的C#属性进行了包装,使用方法与普通的属性是相同的。1.1依赖属性提供的属性功能资源数据绑定样式动画元数据重写属性值继承WPF设计器集... 查看详情

wpf依赖属性1

...是每个.net程序员都必须熟悉的特性,但是在wpf中引入了依赖属性的概念,依赖属性和原来属性的定义完全不一样,wpf通过依赖属性改变了元素属性的定义方式,依赖属性为wpf的数据绑定、动画以及样式,都起到了关键的作用,... 查看详情