Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR)属性的功能,这些服务通常统称为 WPF 属性系统。由 WPF 属性系统支持的属性称为依赖项属性。

  这段是MSDN上对依赖属性(DependencyProperty)的描述。主要介绍了两个方面,WPF中提供了可用于扩展CLR属性的服务;被这个服务支持的属性称为依赖属性。

  单看描述,云里雾里的,了解一个知识,首先要知道它产生的背景和为什么要有它,那么WPF引入依赖属性是为了解决什么问题呢?

属性是我们很熟悉的,封装类的字段,表示类的状态,编译后被转化为get_,set_方法,可以被类或结构等使用。 一个常见的属性如下:

   1: public class NormalObject

   2: {

   3:     private string _unUsedField;

   4:  

   5:     private string _name;

   6:     public string Name

   7:     {

   8:         get

   9:         {

  10:             return _name;

  11:         }

  12:         set

  13:         {

  14:             _name = value;

  15:         }

  16:     }   

  17: }

在面向对象的世界里,属性大量存在,比如Button,就大约定义了70-80个属性来描述其状态。那么属性的不足又在哪里呢?

  当然,所谓的不足,要针对具体环境来说。拿Button来讲,它的继承树是Button->ButtonBase->ContentControl->Control->FrameworkElement->UIElement->Visual->DependencyObject->…

  每次继承,父类的私有字段都被继承下来。当然,这个继承是有意思的,不过以Button来说,大多数属性并没有被修改,仍然保持着父类定义时的默认值。通常情况,在整个Button对象的生命周期里,也只有少部分属性被修改,大多数属性一直保持着初始值。每个字段,都需要占用4K等不等的内存,这里,就出现了期望可以优化的地方:

  • 因继承而带来的对象膨胀。每次继承,父类的字段都被继承,这样,继承树的低端对象不可避免的膨胀。
  • 大多数字段并没有被修改,一直保持着构造时的默认值,可否把这些字段从对象中剥离开来,减少对象的体积

依赖属性的优点

  回过头来,总结一下依赖属性的优点:

  • 优化了属性的储存,减少了不必要的内存使用。
  • 加入了属性变化通知,限制、验证等,
  • 可以储存多个值,配合Expression以及Animation等,打造出更灵活的使用方式。

总结

  借助于依赖属性,WPF提供了强大的属性系统,可以支持数据绑定、样式、动画、附加属性等功能。这篇文章主要是简略的实现了一个从属性到依赖属性的发展过程,当然,具体和WPF的实现还有偏差,希望朋友们都能抓住这个主要的脉络,更好的去玩转它。

  除了依赖属性的实现,还有一些很重要的部分,比如借助于依赖属性提出的附加属性,以及如何利用依赖属性来更好的设计实现程序,使用依赖属性有哪些要注意的地方。呵呵,那就,下篇吧。

有一个小技巧,需要申明一个依赖属性并使用CLR属性封装时,只需要输入propdp,vs就会给出一个提示,连按两次tab键,一个标准被依赖属性就申明好了,继续按tab键,可以修改依赖属性的各个参数。

怎么样才能使一个属性成为依赖项属性呢?

首先,属性所在的类要直接或间接继承DependencyObject。这个类生成的对象表示一个具有依赖项属性的对象,这些对象,都能享用WPF的属性系统(属性系统主要是计算属性的值,并提供有关值已更改的系统通知)方面的服务。

这个类有两个比较重要的方法,GetValue(返回当前对象依赖项属性的当前有效值)和SetValue(设置依赖项属性的本地值)。

其实,属性对应的字段必需是公有,静态,只读的,类型为DependencyProperty。即public static readonly DependencyProperty 字段名,同时字段的命名也有规范,属性名+Property,字段在定义时,通过DependencyProperty.Register来实注册属性(只有注册了,才能使用WPF属性系统的服务)。

Register方法有三种重载,如下:

名称

说明

Register(String, Type, Type)

使用指定的属性名称、属性类型和属性所在对象的类型。

Register(String, Type, Type, PropertyMetadata)

使用指定的属性名称、属性类型、属性所在对象的类型和属性元数据注册依赖项属性。

Register(String, Type, Type, PropertyMetadata, ValidateValueCallback)

使用指定的属性名称、属性类型、属性所在对象的类型、属性元数据和属性的值验证回调来注册依赖项属性。

在Register中,各个参数解释如下:

String:依赖属性的名字(不加Property,即字段的名字);

Type:属性的类型;

Type:属性所属对象的类型;

PropertyMetadata:依赖项对象的属性元数据,是一个PropertyMetadata类型,可能赋初始值。PropertyMetadata有一个object的构造函数;

ValidateValueCallback:表示用作回调的方法,这个类型是一个委托,用于验证依赖项属性的值的有效性,因为是委托,故它的构造参数为一个方法名。

最后,来构造依赖属性,与普通的属性有所区别:

Public 属性类型 属性名

{

Get

{

return (属性类型)this.GetValue(字段名);

}

Set

{

this.SetValue(字段名, value);

}

}

其中的GetValue和SetValue都是调用父类DependencyObject的方法。

完整的代码如下:

代码 

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 class MyClass : DependencyObject
{
public static readonly DependencyProperty MyfieldProperty = DependencyProperty.Register("Myfield", typeof(int),
typeof(MyClass), new PropertyMetadata(0), new ValidateValueCallback(new MyClass().MyValidateMethod));
public int Myfield
{
get { return (int)GetValue(MyfieldProperty); }
set { SetValue(MyfieldProperty, value); }
}
public bool MyValidateMethod(object value)
{
return true;//这里实现验证
}
}

举例

举例:修改DataGrid的表头

(1)PlotView.xml.cs文件:

public string ColumnName5
        {
            get { return (string)GetValue(ColumnName5Property); }
            set { SetValue(ColumnName5Property, value); }
        }
        public static readonly DependencyProperty ColumnName5Property =
            DependencyProperty.Register("ColumnName5", typeof(string), typeof(PlotView), new UIPropertyMetadata("", new PropertyChangedCallback(ColumnName5PropertyCall)));
        private static void ColumnName5PropertyCall(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PlotView send = d as PlotView;
            if (send.PlotViewDataGrid.Columns.Count > 6)
            {
                send.PlotViewDataGrid.Columns[0].Header = (string)e.NewValue;
            }
        }

(2)MainView.xml文件:

<DataTemplate DataType="{x:Type local:PlotViewModel}" x:Key="PlotTemplate">
            <local:PlotView  ColumnName5="{Binding ColumnName5}"/>
        </DataTemplate>

(3)在PlotViewModel.cs文件

public string ColumnName5
        {
            get
            {
                return ((PlotModel)Model).columnName5;
            }
            set
            {
                if (((PlotModel)Model).columnName5 != value)
                {
                    ((PlotModel)Model).columnName5 = value;
                }
                RaisePropertyChanged("ColumnName5");
            }
        }

(4)在MainViewModel.cs文件:

if (true)
            {
                ((PlotViewModel)this.PlotViewModel).ColumnName0 = "时间"
                
            }
            else
            {
                ((PlotViewModel)this.PlotViewModel).ColumnName0 = ”名称“
 
            }

WPF的依赖属性的更多相关文章

  1. wpf 的依赖属性只能在loaded 事件之后才能取到

    wpf 的依赖属性只能在loaded 事件之后才能取到,在构造函数的  InitializeComponent(); 之后取不到 wpf 的依赖属性只能在loaded 事件之后才能取到,在构造函数的  ...

  2. WPF 中依赖属性的继承(Inherits)

    WPF中依赖属性的值是是可以设置为可继承(Inherits)的,这种模式下,父节点的依赖属性会将其值传递给子节点.例如,数据绑定中经常使用的DataContextProperty: var host ...

  3. WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性

    原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? ...

  4. WPF的依赖属性和附加属性(用法解释较全)

    转:https://www.cnblogs.com/zhili/p/WPFDependencyProperty.html 一.引言 感觉最近都颓废了,好久没有学习写博文了,出于负罪感,今天强烈逼迫自己 ...

  5. WPF利用依赖属性和命令编写自定义控件

    以实例讲解(大部分讲解在代码中) 1,新建一个WPF项目,添加一个用户控件之后在用户控件里面添加几个控件用作测试, <UserControl x:Class="SelfControlD ...

  6. WPF: 只读依赖属性的介绍与实践

    在设计与开发 WPF 自定义控件时,我们常常为会控件添加一些依赖属性以便于绑定或动画等.事实上,除了能够添加正常的依赖属性外,我们还可以为控件添加只读依赖属性(以下统称"只读属性" ...

  7. WPF 自定义依赖属性

      原博客地址:http://www.cnblogs.com/DebugLZQ/archive/2012/11/30/2796021.html    DependencyObject和Dependen ...

  8. [转]WPF的依赖属性是怎么节约内存的

    WPF升级了CLR的属性系统,加入了依赖属性和附加属性.依赖属性的使用有很多好处,其中有两点是我认为最为亮眼的: 1)节省内存的开销; 2)属性值可以通过Binding依赖于其它对象上,这就使得我的数 ...

  9. WPF 之 依赖属性与附加属性(五)

    一.CLR 属性 ​ 程序的本质是"数据+算法",或者说用算法来处理数据以期得到输出结果.在程序中,数据表现为各种各样的变量,算法则表现为各种各样的函数(操作符是函数的简记法). ...

随机推荐

  1. DirectoryEntry 活动目录的使用

    public class DirectoryHelper { public static string DomainName = System.Environment.UserDomainName; ...

  2. day-3

    /* 快noip了!!!感觉还有好多事要做 上午考试 原题没做 自己找了套题 挺水的 T1模拟(然而没认真读题 90) T2 dp+简单优化 数据有点问题 T3 暴力状丫 然而写丑了 60分的要两秒多 ...

  3. 推荐几个对Asp.Net开发者比较实用的工具

    推荐几个对Asp.Net开发者比较实用的工具.大家有相关工具也可以在评论区留言,一起努力学习. 工具 1.Visual stdio Productivity Power tool:visual std ...

  4. [转]SharePoint 2010/2013 使用Javascript来判断权限的三种方法

    本文讲述SharePoint 2010/2013 使用Javascript来判断权限的三种方法的实现方式及其优缺点. 1. 根据用户所在的SharePoint组(比如用户在Leader 组才可以使用审 ...

  5. ecshop在PHP 5.4以上版本各种错误问题处理

    在php5.4版本之后有很多的函数与功能进行丢弃与升级功能了,现在国内很多CMS都还未按php5.4标准来做了,下面我整理了一些在ecshop在PHP 5.4以上版本各种错误问题处理. 1.PHP 5 ...

  6. 如何注册ActiveX打印控件

    一.看系统是32位还是64位的.(以64位为例) 二.先找到你的wfPrint.OCX文件所在路径 三.找到SysWOW64所在的命令控制符 四.最后在该cmd下注册 就可以了.

  7. CentOS 6.4安装OpenOffice

    终端依次输入: (1)sudo yum install openoffice.org-writer (2) sudo  yum install openoffice.org-calc (3) sudo ...

  8. Java I/O重定向

    1.输入重定向 命令行:java [java类文件] < [输入文件路径名] 代码:InputStream inputStream = new FileInputStream(          ...

  9. ios-异步消息同步问题-典型使用场景: 微信私信界面

    前言 在ios开发中常常会有聊天功能,一般简单聊天功能只传输文字,但是稍微复杂点儿会有图片发送功能了.最全而且可支持扩展的例如微信,qq 聊天功能了.传输方式各有千秋,如get,post,websoc ...

  10. Solr使用初探——Solr的安装环境与配置

    Solr是一个apache名下很好用的开源索引.搜索工具,网上的资料虽多但很杂,笔者花了一天的时间对Solr进行了较为初步的研究,对Solr的基础应用做了一定的总结.文中涉及到的配置方法并不唯一,AP ...