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等。
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等。
相关文章推荐
- 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(一)
- 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(二)
- 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(三)
- ArcGIS API for Silverlight/WPF 2.1学习笔记(一)——精简版
- 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(四)
- 【转】ArcGIS API for Silverlight/WPF 2.1学习笔记(五)
- Fast.ai: Practical Deep Learning for coders 课程学习笔记:Part1 Lesson1 (Lesson0)
- Fast.ai: Practical Deep Learning for coders 课程学习笔记:Part1 Lesson1 (Lesson0)
- DWR: Easy AJAX for JAVA 学习笔记
- 【转】shell学习笔记(六)——流程控制之for循环
- WPF and Silverlight 学习笔记(二十九):Brush(1)
- A guide to Matlab for Beginners and Experienced Users——学习笔记【2】
- WPF and Silverlight 学习笔记(三十):Brush(2)
- wpf学习笔记
- WCF 学习笔记 (1) - Specify Fault Behaviors for the Service
- Arcgis api for javascript学习笔记-三维地图的飞行效果
- Python学习笔记--for, while循环后面加else的作用
- WPF学习笔记--一些新鲜的控件
- Java for Web学习笔记(二七):JSTL(3)Core Tag(中)