首页 / 软件开发 / .NET编程技术 / 《Programming WPF》翻译 第9章 3.自定义功能
《Programming WPF》翻译 第9章 3.自定义功能2011-09-16 博客园 包建强一旦你挑选好一个基类,你将要为你的控件设计一个API。大部分WPF元素提供属性暴露了多数功能, 事件,命令,因为他们从框架中获取广泛的支持,以及易于使用XAML。WPF框架对routed event和命令提 供了自动支持,它的依赖属性系统提供了数据半岛和动画支持。当然,你也可以写方法——对于某一种功 能,方法是最好的途径。(例如,ListBox有一个ScrollIntoView方法,保证了一个特定的项目是可见的 。这时从代码中能够做的方便的事情。)但是,我更喜欢在合理的地方使用属性,事件以及命令。9.3.1属性.NET类型系统提供了一个标准的方式为一个对象定义属性。它指定了一个协定:提供了get和set的方 法访问器,但是对于这些的实现,以及属性值的存储方式,都留给了开发者。在WPF中,元素通常使用依 赖属性系统。.NET提供了代表性的样式属性访问器,但是这些仅仅是对依赖属性(DP)的包装,增加了便 利。DP系统添加了大量的特色——并不有标准.NET属性提供。例如,DP从父元素中继承了它的值。这与OO 意义上的继承不同,DP是从其基类继承其特征(虽然DP也支持OO意义的继承性)。属性值的继承性是一个 更动态的特征,允许在一个单元素上设置属性,以及自动传播到它的所有子元素。例如,所有的元素有一 个Cursor属性用来控制鼠标指针。这个属性使用了值的继承性,意味着一旦你在元素上看到Cursor,所有 的子元素将自动得到同样的Cursor属性值。(如果你使用Windows Forms,你将熟悉这个概念,这里任意 的元素都具有相同的特征。)DP在别处也自动获取它们的值。DP支持数据绑定和样式,它们提供一个定义默认值的机制。动画系统 也依赖于DP,它使用了DP结构来即时的调整属性值。通过实现你的元素属性,如DP,你不仅可以自动得到这些特征,而且DP系统还为你管理着值的存储。 你不必为定义任何字段实例来存储属性值。存储管理器看起来是件小事情,毕竟,为类添加一个字段是多么的困难?尽管如此,这种特征能提供 令人惊讶的有意义的内存存储。简单的继承于Control,你的元素可以支持多于40个属性(加上任何附属属性)来改变复杂性,其中大 部分看起来都具有一个默认值对于大多数对象而言。如果每个元素都有自己的一组字段存储这些值,每个 元素将占用数百字节。一个复杂的用户界面可能需要成千的字节(即使UI有一个相当简单的结构,可视化 树可以显著地增加元素的数量。)多数元素的大部分属性或者继承与它们的父类或者设置为它们的默认值,然后使用元素按字段存储这 些值,这将浪费成百上千的内存。更加高级的存储方式暴露了这样的事实:多数未设置的属性是有效的。 而且随着内存的便宜,在CPU中移入移出数据是昂贵的。CPU可以比数据转换主内存, 更快的执行代码。只 有内存缓存可以相当快的跟上处理器,而且大多数现代化的处理器典型地只有成百上千字节的缓存。甚至 高端系统仅有几个兆字节的缓存。保存成百上千字节能够显著的提高性能。采取DP系统,我们可以让它更加有效地处理信息——通过仅对显示设定的属性值排序。最后,DP系统跟踪了值的改变。这意味着一旦任何感兴趣的部分想知道一个属性值何时改变,它能使 用DP系统注册通知。(数据绑定取决于次。)我们不需要写任何特殊的代码使之发生。DP系统管理者我们 属性值的存储,因此它知道何时属性改变。任何你创建的WPF自定义元素,将会自动地支持DP的一切,因为FrameworkElement间接派生于 DependencyObject基类。为了在我们的自定义元素上定义一个新的属性,我们必须在元素的静态构造函数 中创建一个新的DependencyObject对象。作为惯例,我们暴露了对象属性,通过在我们的类中,按一个公 有的静态字段排序,正如示例9-1所示。