和传统属性的区别在哪里,为什么要搞出这样一个DependencyProperty呢?

  • 内存使用量。
    我们设计控件,不可避免的要设计很多控件的属性,高度,宽度等等,这样就会有大量(私有)字段的存在,一个继承树下来,低端的对象会无法避免的膨胀。而外部通过GetValue,SetValue暴露属性,内部维护这样一个EffectiveValueEntry的数组,顾名思义,只是维护了一个有效的、设置过值的列表,可以减少内存的使用量。
  • 传统属性的局限性。
    这个有很多,包括一个属性只能设置一个值,不能得到变化的通知,无法为现有的类添加新的属性等等。

在 MSDN 中,提到当你有下面四种情况时,应该考虑使用DependencyProperty:

  • 您希望可在样式中设置此属性。
  • 您希望此属性支持数据绑定。
  • 您希望此属性支持经过动画处理的值。
  • 您希望 Silverlight 属性系统在属性系统本身、环境或用户执行的操作或者读取并使用样式而更改了属性以前的值时进行报告。您的属性可以指定在每次属性系统确定属性值已被明确更改时将调用的回调方法。

一个Silverlight中创建 DependencyProperty 的例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
namespace SilverlightApplication2
    public partial class SilverlightControl1 : UserControl
        /// Declare the dependency property as static, readonly field in your class.    
        public static readonly DependencyProperty AquariumGraphicProperty 
            = DependencyProperty.Register(
          "AquariumGraphic",                                        // Property name
          typeof(Uri),                                              // Property type
          typeof(SilverlightControl1),                              // Type of the dependency property provider
          new PropertyMetadata(null,                                // 默认的值
              new PropertyChangedCallback(OnUriChanged)               // Callback invoked on property value has changes
        /// Create the property and use the SetValue/GetValue methods of the DependencyObject class
        public Uri AquariumGraphic
            get { return (Uri)GetValue(AquariumGraphicProperty); }
            set { SetValue(AquariumGraphicProperty, value); }
        public SilverlightControl1()
            InitializeComponent();
        /// 值变化时,更新显示
        private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            Shape sh = (Shape)d;
            ImageBrush ib = new ImageBrush();
            ib.ImageSource = new BitmapImage(e.NewValue as Uri);
            sh.Fill = ib;

我们首先来看看 AquariumGraphicProperty ,类型就是DependencyProperty,前面用了static readonly,一个单例模式,有DependencyProperty.Register,看起来像是往容器里注册,其实也差不多。

再来看AquariumGraphic,和传统的属性没什么区别,类型是 Uri 型,有get,set方法。只不过内部的实现分别调用了GetValue和SetValue,这两个方法是DependecyObject(简称DO,是WPF/Silverlight中所有可视Visual的基类)暴露出来的,传入的参数是AquariumGraphicProperty。

需要注意的是运行时,Xaml中是直接调用GetValue和SetValue的。所以,为了让使用XAML设置属性与使用代码设置属性一致,在属性包装器中除了GetValue和SetValue调用以外,不应该包含任何其他逻辑,这是非常重要的。如果需要添加自定义逻辑,应该在Register的回调函数中添加。

参考资料:

.Net3.0里的DependencyProperty(1):引入了DP的一些基本概念
http://www.cnblogs.com/yayx/archive/2007/05/26/761117.html

WPF里的DependencyProperty(2):DP的应用,主要想解释我们为什么要用它
http://www.cnblogs.com/yayx/archive/2008/04/20/1162963.html

WPF里的DependencyProperty(3):主要想演示下怎么用DP
http://www.cnblogs.com/yayx/archive/2008/04/22/1166064.html

WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法? :附属,从布局应用上解释了下为什么要有AttachedProperty
http://www.cnblogs.com/yayx/archive/2008/04/23/1167110.html

WPF里的DependencyProperty(4):介绍了DP的工作机制
http://www.cnblogs.com/yayx/archive/2008/04/24/1168738.html

WPF里的DependencyProperty(5) :介绍了PropertyMetadata和AttachedProperty
http://www.cnblogs.com/yayx/archive/2008/06/03/1213126.html

Windows Presentation Foundation 体系结构
http://msdn.microsoft.com/en-us/ms750441(zh-cn).aspx

如何学好WPF
http://www.cnblogs.com/zhouyongh/archive/2009/07/31/1536000.html

Tip: How to declare a dependency property in Silverlight?
http://www.silverlightshow.net/tips/Tip-How-to-declare-a-dependancy-property-in-Silverlight.aspx

WPF体系结构-- System.Windows.DependencyObject与智能的控件
http://bbniu.com/forum/thread-478-1-1.html

图解DotNet框架之九:WPF
http://www.cnblogs.com/xugao918/archive/2008/08/01/1258193.html

Silverlight自定义依赖项对象和依赖项属性
http://msdn.microsoft.com/zh-cn/library/cc903933(VS.95).aspx

这一篇Post中,我准备先介绍WPFDependencyProperty的一些基本用法。   在程序中使用DependencyProperty好的,我相信你已经决定了要使用DependencyProperty而不是传统的CLR属性,正如上一篇Post所说,很多地方都需要使用到DependencyProperty,作为例子,我决定定义一个MyBorderEx,在WPF常用的"Border 解决的问题:一个控件可能有几百个CLR属性,如果每个CLR属性都是包装一个字段,那么这个控件耗费的内存太大了。依赖属性就是解决这个问题的。 如何解决这个问题:使控件的CLR属性不是包装字段,而是包装一个DependencyProperty,并且这个DependencyProperty的内存不是分配在控件内,而是采用某种机制分配在外部,以key-value的形式存在。另外,DependencyPr...  Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR) 属性的功能,这些服务通常统称为 WPF 属性系统。由 WPF 属性系统支持的属性称为依赖项属性。  这段是MSDN上对依赖属性(DependencyProperty)的描述。主要介绍了两个方面,WPF中提供了可用于扩展CLR属性的服务;被这个服 依赖属性并不是一种语言层面的 "属性",而是一种 WPF 提供的 "功能"。它在 CLR Property 的基础上封装了一些内在的行为,使得基于声明式的 XAML 具备更强大的动作操控能力,很显然这比使用程序设计代码编写行为事件要简便和自然得多。依赖属性的特点:(1) 使用高效的稀疏存储系统,这意味着在不设置本地值的情况下,所有同类型对象的依赖属性都将共享默认设置,大大节约内存开销。(2) 依赖 依赖属性DependencyPropertywpf最重要的一个类,理解该类如何实现对学习wpf帮助很大! 终于找到了该类的源码!仔细阅读源码,看看微软如何玩的花招! 1 File: Base\System\Windows\DependencyProperty.cs 2 Project: wpf\src\WindowsBase.csproj (WindowsBase) 1. 概述 依赖属性(DependencyProperty)是UWP的核心概念,它是有DependencyObject提供的一种特殊的属性。由于UWP的几乎所有UI元素都是集成于DependencyObject的FramewordElement,并且这些UI元素的几乎所有属性及它们出现在XAML中的几乎所有属性都是依赖属性,所以可以说依赖属性是专门为UI设计的属性系统。 依赖属性的定义: ///... 尽管一个类会提供很多事件,但有时候还是显得不够,比如说前两天我就以为WPF的ListBox控件会有ItemsSourceChanged事件,但好像没有。这里有一个方法可以监视任何一个DependencyProperty的Changed,下面是demo: