您的位置:首页 > 其它

WPF学习笔记:Templates for uncommon controls

2010-03-13 07:09 316 查看
Templates for uncommon controls

http://msdn.microsoft.com/en-us/magazine/cc135986.aspx

是该文章的读书摘记

以前的控件其外观代码和逻辑代码是帮定在一起的,如果你想改变一个控件的外观,你需要从那个控件的类派生,重写显示外观部分的代码。甚至有的时候,这样做也达不到你的目标。而在WPF中,逻辑和外观代码可以分离。利用Template可以很方便的改变控件的外观而不改变其功能。所有的WPF控件都有默认的 Template,你可以方便的替换鲜有的template而改变Control的外观和显示。

Element 和Control的区别

在WPF中Control类从FrameworkElement类派生 ,像TextBlock, Image, Panel, Decorator等都从FrameworkElement直接派生,所以他们不是Control.

首先Control增加了很多属性,例如Foreground, Background 以及五个与Font有关的属性

其次Control增加了IsTabStop和TabIndex属性,这使得Control可以相应Tab键的焦点切换,而FrameworkElement 则没有这个功能,一句话,FrameworkElement仅仅是为了外观,而 Control还增加了交互。

再者,Control有template, 可以被替换template而改变外观,template基本上就是代表控件外观的一颗视觉树,当然也包括响应属性变化和事件的一些triggers。

所以如果你要创建自己的Control,那么很重要的一点就是你要提供可替换的默认的template,尽管这不是必须的,但是这样做无疑会极大地改善你的Control的易用性。

要为你的Control DLL提供一个可被替换的默认的Template, 你必须遵守WPF的严格的规则:

1. 你的源代码项目下必须有一个Theme目录,包含一个叫General.xaml的文件

2. General.xaml是一个Style的ResourceDictionary

3. Style中必须包含设置Template属性的Section

<RecourceDictonary>

<Style TargetType="cc:CaladendarDay">

<Setter Property="Template">

<Setter.Value>

<ControlTemplate TargetType="..." >

.....

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

</ResourceDictonary>

4. 在你的控件类的静态构造函数中改变DefaultStyleKeyProperty属性的默认值:

一般来说你设计一个控件,会从Control派生,并且增加一些属性。那么这里最好背后都是用DependencyProprty, 以使得这些属性可以Data Binding,并且利用Routed Event机制,在你的属性改变的时候,其他相关的对象得到通知。

如果你需要属性已经在其他类里面定义过了,不要重新定义它,需要AddOwner

使用DependencyProperty.OverrideMetaData可以用来改变从父类Control继承过来的Dependency属性的默认值,以及注册一个回调函数在属性改变的时候被0调用。

覆盖OnApplyTemplate函数,以便检验Template的合法性以及建立与代码与template的连接,因为你或许需要Template中有指定的part, 例如ItemsControl都有一个叫PART_Panel的panal

在template中使用TemplateBinding绑定到那些新定义的DependencyProperty, 这样这些属性的改变就会反映到控件的外观上。对于那些可以通过视觉树从Control类继承的属性则不需要做任何处理,会自动应用到控件的外观上。例如 Foreground以及5个与Font相关的属性就会自动的应用于控件的外观,而不需要我们在Template中使用TemplateBinding来绑定。

在Template中应该尽量少的使用硬编码来设置一些属性的值,这样使用控件的人如果需要修改这些默认值就会很麻烦。一种可行的方法是,直接在Style中设置这些值,而不是在Template中设置这些值。这样控件的使用者就可以很方便的修改这些值。

如果你的代码会假定Template 中必须有某些类型的部件,那么最好用TemplatePart属性在你的Control的派生类上来标明。

[TemplatePart(Name="PART_Panel", Type=TypeOf(Panel))]

public class CalandarDay: Control

{ ....

}

你的Control派生类最好也可以暴露出一些RoutedCommand对象,使得 Template可以帮定以执行一些功能。

public static readonly RoutedCommand NextMonthCoommand = new RoutedCommand("NextMonth", typeof(CalendarMonth));

其实只有少数WPF控件可以绑定到RoutedCommand, ButtonBase, MenuItem, HyperLink等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: