依赖属性就是一种可以自己没有值,并能通过使用Binding从数据源获得值(依赖在别人身上)的属性。拥有依赖属性的对象称为“依赖对象”。

WPF开发中,必须使用依赖对象作为依赖属性的宿主,使二者结合起来。依赖对象的概念被DependencyObject类所实现,依赖属性的概念则由DependencyProperty类所实现

从这棵继承树上可以看出,WPF的所有UI空间都是依赖对象。

看最简单的依赖属性

class Student : DependencyObject
{ public string Name
{
get { return (string)GetValue(NameProperty); } //依赖属性和附加属性定义的不同
set { SetValue(NameProperty, value); }
} public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(Student));
}

实例并非使用new操作符得到而是使用DependencyProperty.Register方法生成。

现在我们使用的Register方法是参数最少,最简单的一个重载,我们来分析一下

  • 第一个参数为string类型,表示指明以哪个CLR属性作为这个依赖属性的包装器。就是代码
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
  • 第二个参数指明此依赖属性用来存储什么样的值。
  • 第三个参数用来指明此依赖属性的宿主是什么类型,或者说DependencyProperty.Register方法要将这个依赖属性注册到哪个类型上。

注意:1.依赖属性包装器是一个CLR属性,并不是依赖属性,没有包装器,依赖属性依旧存在。

2.既然没有包装器依赖属性也存在,那么包装器是干什么用的呢?包装器的作用是以“实例属性”的形式向外界暴露依赖属性,这样,一个依赖属性才能成为数据源的一个Path。

3.注册依赖属性时使用的第二个参数是一个数据类型,这个数据类型也是包装器的数据类型。

请看例子

<Window x:Class="DependencyPropertySample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox x:Name="textbox1" BorderBrush="Black" Margin="5"/>
<TextBox x:Name="textbox2" BorderBrush="Black" Margin="5"/>
<Button Content="OK" Margin="5" Click="Button_Click"/>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void Button_Click(object sender, RoutedEventArgs e)
{
Student stu = new Student();
stu.SetValue(Student.NameProperty, textbox1.Text);
textbox2.Text = (string)stu.GetValue(Student.NameProperty); //依赖属性代码用法
}
}

当第一次看到这个例子的时候,也许会有点百思不得其解的感觉——依赖属性不是一个Static对象么?哪怕有1000个Student实例,依赖属性只有一个啊,那么SetValue把值存储到哪里去了?GetValue又从哪里读取值?并且,依赖属性不是一个只读的吗?怎么可以写入值呢?其实这个问题直指依赖属性机制的核心,我们过一会再讨论。

还要注意一点,尽管student类没有实现INotifyPropertyChange接口,当属性的值发生改变时与之关联的Binding对象依然可以得到通知,依赖属性默认带有这样的功能,天生就是合格的数据源。

使用vs2010有一个小技巧,生成依赖属性可以使用代码段propdp,DependencyProperty.Register带4个参数,第四个参数的类型是PropertyMetadata类,作用是给依赖属性的DefaultMetadata属性赋值。顾名思义,DefaultMetadata的作用就是向依赖属性的调用者提供一些基本信息,这些信息包括:

  • CoerceValueCallback:依赖属性的值被强制改变时此委托会被调用,此委托可关联一个函数。
  • DefaultValue:依赖属性未被显示赋值时,若读取之则获得此默认值,不设置此值会抛出异常。
  • IsSealed:控制PropertyMetadata的属性值是否可以更改,默认值为true。
  • PropertyChangeCallback:依赖属性的值被改变之后此委托会被调用,此委托可关联一个函数。

注意:依赖属性的DefaultMetadata只能通过Register方法的第四个参数惊醒赋值,而且一旦赋值就不能改变。如果想用新的PropertyMetadata替换这个默认的Metadata,需要使用DependencyProperty.OverrideMetadata方法。

下面我们来解决刚才的红色问题。

首先值存到什么地方去了?

创建一个DependencyProperty实例并用它的CLR属性名和宿主类型名生成hash code,最后把hash code和DependencyProperty实例作为Key-Value对存入全局的,名为PropertyFormName的Hashtable中。

。。。(我认为书上写的太深奥啦,想要深究的同学可以参考《深入浅出WPF》)

初学者不必深究,那就是使用了static和readonly是为了保证DependencyProperty的索引值唯一。真正的值是存在一个Hashtable中的,当然可读可写啦。

Dependency Property 依赖属性的更多相关文章

  1. WPF学习笔记——依赖属性(Dependency Property)

    1.什么是依赖属性 依赖属性是一种可以自己没有值,并且通过Binding从数据源获得值(依赖在别人身上)的属性,拥有依赖属性的对象被称为"依赖对象". 依赖项属性通过调用 Regi ...

  2. WPF整理-为User Control添加依赖属性

    依赖属性 ".NET properties are nothing more than syntactic sugar over set and get methods." 我们知 ...

  3. WPF入门教程系列十二——依赖属性(二)

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

  4. WPF依赖属性详解

    WPF依赖属性详解 WPF 依赖属性 英文译为 Dependency Properties,是WPF引入的一种新类型的属性,在WPF中有着极为广泛的应用,在WPF中对于WPF Dependency P ...

  5. WPF快速入门系列(2)——深入解析依赖属性

    一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己开始更新WPF系列.尽管最近看到一篇WPF技术是否老矣的文章,但是还是不能阻止我系统学习WPF.今天继续分享WPF中一个最 ...

  6. WPF基础到企业应用系列7——深入剖析依赖属性(WPF/Silverlight核心)

    一. 摘要 首先圣殿骑士非常高兴这个系列能得到大家的关注和支持.这个系列从七月份開始到如今才第七篇,上一篇公布是在8月2日,掐指一算有二十多天没有继续更新了,最主要原因一来是想把它写好,二来是由于近期 ...

  7. silverlight依赖属性

    依赖属性(Dependency Property)和附加属性(Attached Property) 参考 http://www.cnblogs.com/KevinYang/archive/2010/0 ...

  8. 重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试

    原文:重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试 [源码下载] 重新想象 Windows 8 Store ...

  9. [UWP]依赖属性2:使用依赖属性

    5. 完整的自定义依赖属性 5.1 定义 /// <summary> /// 标识 Title 依赖属性. /// </summary> public static reado ...

随机推荐

  1. python 字典的KeyError处理方法

    先看一段代码: user = dict(name="brainliao", age=32) print(user["sex"]) 运行结果如下: user这个字 ...

  2. ITFriend创业阶段的server环境搭建手冊

    创业阶段,进一步实践了Linux环境搭建和维护,以下是一些经常使用软件的搭建步骤和參考资料,仅供自己和诸位參考. 我个人还是比較倾向"一站式Web开发"的.自己想做点事.须要太多的 ...

  3. 07-hibernate进阶

    1,hibernate.cfg.xml常用配置 2,session简介 3,transaction简介 4,session详解 5,对象关系映射常用配置 hibernate.cfg.xml常用配置 s ...

  4. flashback database(drop tablespace)

    1.首先记录时间 select to_char(systimestamp,'yyyy-mm-dd HH24:MI:SS') from dual;--2014-04-25 13:55:48 查看表sel ...

  5. 关于cnblogs的排版

    cnblogs默认的样式实在让我无法接受.今天去看了看div+css的基本知识. 决定这周抄一个别人的排版,稍微改改. 不然,就这样式,实在没心情写博客. 写博客,这次准备要大干一场了.

  6. docker运行环境安装-centos(一)

    在这里我们使用的是docker的社区版Docker CE,针对的是未安装docker的新的主机,如果安装过docker的早期版本,先卸载它们及关联的依赖资源,安装的版本为docker 18.03. 1 ...

  7. RESTORE DATABASE命令还原SQLServer 数据库 bak

    今天在sqlServer20005 的management studio里使用bak文件还原数据库的时候,总是失败!Restore failed for Server 'ADANDELI'.  (Mi ...

  8. SiteWhere物联网云平台架构

    SystemArchitecture系统架构 Thisdocument describes the components that make up SiteWhere and how theyrela ...

  9. linode下更换内核(debian,ubuntu,centos)

    1.首先到这个网址下载你需要得内核文件,以genric:http://kernel.ubuntu.com/~kernel-ppa/mainline/ 如果系统是 64 位,则下载 amd64 的 li ...

  10. 完整学习使用CSS动画【翻译】

    注:原文有较大改动 使用keyframes, animation属性,例如timing,  delay, play state, animation-count, iteration count, d ...