加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

依赖属性

发布时间:2020-12-14 05:33:24 所属栏目:百科 来源:网络整理
导读:依赖属性是WPF中的概念,很多WPF书籍用专门的一章来讲解,初学者经常迷惑,我多次给同事网友解释过。 本文的目的就是想把简单的事情讲清楚,如果你是初学者,欢迎光临。如果你早已熟悉,谢谢光临。 (一)首先我们来看看普通的属性和依赖属性的定义方式:?
依赖属性是WPF中的概念,很多WPF书籍用专门的一章来讲解,初学者经常迷惑,我多次给同事网友解释过。
本文的目的就是想把简单的事情讲清楚,如果你是初学者,欢迎光临。如果你早已熟悉,谢谢光临。

(一)首先我们来看看普通的属性和依赖属性的定义方式:?

【普遍属性】

public ? class ?MyTextBlock
{
????
private ? double ?_fontSize? = ? 12 ;
????
public ? double ?FontSize?{? get ?{? return ?_fontSize;?}? set {?_fontSize? = ?value;?}?}

}?

?

【依赖属性】?

public? class ?MyTextBlock?:?DependencyObject?

{
????public?static?readonly?DependencyProperty?FontSizeProperty?=
????????DependencyProperty.Register("FontSize",?typeof(double),?typeof(MyTextBlock),?12.0/*缺省值*/);

????
public?double?FontSize
????{
????????
get?{?return?(double)base.GetValue(FontSizeProperty);?}
????????
set?{?base.SetValue(FontSizeProperty,?value);?}
????}
}

第一点:要定义一个static readonly的类型为DependencyPropertyFontSizeProperty字段;

第二点:MyTextBlock要直接或间接继承 D ependencyObject
第三点:在FontSize属性的get中调用基类( DependencyObject)的GetValue,在set中调用基类的SetValue;
其中第一点, FontSizePropertystatic。这是初学者最容易迷惑的。为什么是 static呢?不管有多少MyTextBlock对象,它们的缺省FontSize都是12,属性名都是“FontSize”
所以FontSizeProperty是 static 。
(二)?依赖属性有什么好处呢?
首先, 节省空间:在一个程序的窗口中会有很多控件,每个控件都有三五十个属性,如果这些属性都是普通属性,那么每个控件就有三五十个字段在内存中, 虽然你根本没有设置过它们,但它们依然存在(占内存)
FontSize就是例子,一般你很少设置它。这样对内存是一种浪费。而依赖属性 只有你设置了才会在内存中存在,不设置就不会存在。这样就节省了空间,如何节省后面会说到。

再有,依赖属性可以应用动画,双向绑定,Style,还可以从可视化树的祖先中继承值,等等很多好处。?

?

(三)?依赖属性是如何实现这些好处的?
从上面依赖属性的定义方式可以看出,最重要的就是 两个类DependencyProperty DependencyObject,后者有两个重要的方法(GetValue和SetValue),

我们来模拟一下这两个类的实现。?

?

1. 先从简单的来:DependencyProperty类,代码很简单,如下:

public? class ?DependencyProperty

{
????private?Type?_propertyType;
????
private?Type?_ownerType;
????
private?string?_name;
????
private?object?_defaultValue;

????
public?object?DefaultValue?{?get?{?return?_defaultValue;?}?}
????
public?string?Name?{?get?{?return?_name;?}?}

????
private?DependencyProperty(string?name,?Type?propertyType,?Type?ownerType,?object?defaultValue)
????{
????????_propertyType?=?_propertyType;
????????_ownerType?=?ownerType;
????????_name?=?name;
????????_defaultValue?=?defaultValue;
????}

????
public?static?DependencyProperty?Register(string?name,?object?defaultValue)
????{
????????
if?(defaultValue.GetType()?!=?propertyType)
????????{
????????????
throw?new?Exception(string.Format("the?type?of?defaultValue?is?not?{0}",?propertyType.Name));
????????}

????????DependencyProperty?dp?=?new?DependencyProperty(name,?propertyType,?ownerType,?defaultValue);
????????????
????????
//再做一些其它的事情,好让dp能获得一些WPF的功能
????????
//可能会用到?ownerType
????????????
????????
return?dp;
????}
}

?

说明:在这里, DependencyProperty没做什么事,只是把Name和缺省值保存起来而已。

?

?

2. 接下来,模拟一下DependencyObject类的实现,代码不难,如下:

public?class?DependencyObject?

{
????private?IDictionary<DependencyProperty,?object>?_dict?=?new?Dictionary<DependencyProperty,?object>();
????????
????
public?void?SetValue(DependencyProperty?p,?object?val)
????{
????????
if?(_dict.ContainsKey(p))
????????{
????????????_dict[p]?=?val;
????????}
????????
else
????????{
????????????_dict.Add(p,?val);
????????}
????}

????
public?object?GetValue(DependencyProperty?p)
????{
????????
//如果被动画控制,返回动画计算值。(可能会用到p.Name)

????????
//如果有本地值,返回本地值
????????if(_dict.ContainsKey(p))
????????{
????????????
return?_dict[p];
????????}

????????
//如果有Style,则返回Style的值
????????
????????
//返回从可视化树中继承的值

????????
//最后,?返回依赖属性的DefaultValue
????????return?p.DefaultValue;
????}
}

说明

DependencyObject用了一个字典来存储属性值。如果你从来没设置过MyTextBlock的FontSize,也就从来没调用过 DependencyObject的SetValue方法,字典中也就不会有FontSize的值。从而节省了空间(要知道MyTextBlock会有几十个依赖属性)。
DependencyObject的GetValue方法, 根据WPF的优先级规则,分别检查动画值,本地值(字典中的值),Style值,如果都没有就返回缺省值。 也就是说SetValue方法做了很多事情,从而让依赖属性比普通属性强大了很多

3. 可以写一小段代码验证一下:如果没设置FontSize,则FontSize返回缺省值,代码很难,如下:?

class ?Program

{
????static?void?Main(string[]?args)
????{
????????
//不设置txt的FontSize属性
????????MyTextBlock?txt?=?new?MyTextBlock();
????????Console.WriteLine(txt.FontSize);

????????
//设置FontSize属性
????????txt.FontSize?=?18;
????????Console.WriteLine(txt.FontSize);
????}
}

?

?最后,上面只是对DependencyPropertyDependencyObject的猜测。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读