浅谈WPF之各种Template

简介: 前几天写了一篇文章【浅谈WPF之控件模板和数据模板】,有粉丝反馈说这两种模板容易弄混,不知道什么时候该用控件模块,什么时候该用数据模板,以及template和itemtemplate之间的关系等,今天专门写一篇文章,简述WPF中各种模板及其相互关系。仅供学习分享使用,如有不足之处,还请指正。

前几天写了一篇文章【浅谈WPF之控件模板和数据模板】,有粉丝反馈说这两种模板容易弄混,不知道什么时候该用控件模块,什么时候该用数据模板,以及template和itemtemplate之间的关系等,今天专门写一篇文章,简述WPF中各种模板及其相互关系。仅供学习分享使用,如有不足之处,还请指正。

 

概述


在WPF中,一共有三种模板,分别如下:

  • 控件模板ControlTemplate,用来指定控件的呈现样式。
  • 数据模板DataTemplate,用来指定子项数据的呈现样式。
  • 子控件模板ItemPanelTemplate,用来指定子项控件的布局样式。

 

模板与控件之间的关系

 

关于各个模板与控件之间的关系,如下图所示:

通过上图可以看出:

  1. Control拥有Template属性,是ControlTemplate类型,所有Control派生的子控件,都具有Template属性,都可以通过控件模板设置控件的样式。
  2. ContentControl拥有ContentTemplate属性,是DataTemplate类型,所有ContentControl派生的控件,都具有ContentTemplate属性,如Button,ListBoxItem,DataGridCell等。
  3. ItemsControl拥有ItemsTemplate属性,是DataTemplate类型,所有ItemsControl派生的控件,都具有ItemsTemplate属性,如ListBox,ComboBox,DataGrid,ListView等。
  4. ItemsControl拥有ItemsPanel属性,是ItemsPanelTemplate类型,所有ItemsControl派生的控件,都具有ItemsPanel属性,如ListBox,ComboBox,DataGrid,ListView等。
  5. Template,ContentTemplate,ItemsTemplate,ItemsPanel只是属性名称,而DataTemlate,ControlTemplate,ItemsPanelTemplate才是模板类型。

 

ControlTemplate控件模板详解

 

利用ControlTemplate可以彻底的颠覆控件的默认外观。<ControlTemplate>里面的内容就是视觉树VisualTree。

两个重要属性:

a)ContentPresenter

重定义控件模板,默认模板将会被覆盖,此时需要利用ContentPresenter,把原有模板的属性原封不动的投放到自定义模板中。

b)Triggers

触发器列表,里面包含一些触发器Trigger,我们可以定制这个触发器列表来使控件对外界的刺激发生反应,比如鼠标经过时文本变成粗体等。

控件模板示例

<Windowx:Class="WpfApplication1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:sys="clr-namespace:System;assembly=mscorlib"Title="MainWindow"Height="350"Width="525"><Window.Resources><ControlTemplatex:Key="rect"TargetType="{x:Type CheckBox}"><ControlTemplate.Resources><SolidColorBrushx:Key="redBrush"Color="Red"/></ControlTemplate.Resources><StackPanel><RectangleName="breakRectangle"Stroke="Red"StrokeThickness="2"Width="20"Height="20"><Rectangle.Fill><SolidColorBrushColor="White"/></Rectangle.Fill></Rectangle><ContentPresenter/></StackPanel><ControlTemplate.Triggers><TriggerProperty="IsChecked"Value="True"><SetterTargetName="breakRectangle"Property="Fill"Value="{StaticResource ResourceKey=redBrush}"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Window.Resources><Canvas><CheckBoxTemplate="{StaticResource ResourceKey=rect}"Content="我是CheckBox"/></Canvas></Window>

注意:<ContentPresenter Margin="{TemplateBinding Padding}" /> 实现了将模板中的Margin绑定到原控件中的Padding上去。

将控件模板写到样式里面,如下所示:

<Stylex:Key="cbx"TargetType="{x:Type CheckBox}"><SetterProperty="Template"><Setter.Value><ControlTemplateTargetType="{x:Type CheckBox}"><ControlTemplate.Resources><SolidColorBrushx:Key="redBrush"Color="Red"/></ControlTemplate.Resources><StackPanel><RectangleName="breakRectangle"Stroke="Red"StrokeThickness="2"Width="20"Height="20"><Rectangle.Fill><SolidColorBrushColor="White"/></Rectangle.Fill></Rectangle><ContentPresenter/></StackPanel><ControlTemplate.Triggers><TriggerProperty="IsChecked"Value="True"><SetterTargetName="breakRectangle"Property="Fill"Value="{StaticResource ResourceKey=redBrush}"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

通过绑定样式资源,如下所示:

<CheckBoxStyle="{StaticResource ResourceKey=cbx}"Content="我是CheckBox"/>

 

c)ItemsPresenter

 

继承自ItemsControl的控件,有一个ItemsPanel属性作为集合元素承载容器。子元素ItemsPresenter负责呈现控件的任务。

只要把ItemsPresenter放在内部模板中,那么ItemsPresenter则会去检测父元素是否为集合控件,然后将ItemsPanel添加到其内部视觉树当中。

<Stylex:Key="{x:Type ItemsControl}"TargetType="{x:Type ItemsControl}"><SetterProperty="Template"><Setter.Value><ControlTemplateTargetType="{x:Type ItemsControl}"><BorderBackground="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"Padding="{TemplateBinding Padding}"SnapsToDevicePixels="true"><ItemsPresenterSnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/></Border></ControlTemplate></Setter.Value></Setter></Style>

比较常见的继承自ItemsControl的控件,比如ComboBox,ContextMenu,ListBox,DataGrid,ListView等。

 

DataTemplate数据模板详解

 

数据模板定义了数据的显示方式,也就是数据对象的可视结构。主要是可以自定义控件的同时进行数据绑定。

<Windowx:Class="WpfApplication1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:sys="clr-namespace:System;assembly=mscorlib"xmlns:src="clr-namespace:WpfApplication1"Title="MainWindow"Height="350"Width="525"><Window.Resources><ObjectDataProviderx:Key="personList"ObjectType="{x:Type src:PersonList}"/><DataTemplatex:Key="rect"><BorderName="border"BorderBrush="Aqua"BorderThickness="1"Padding="5"Margin="5"><StackPanel><StackPanelOrientation="Horizontal"><TextBlockText="{Binding Name}"Margin="5,0,0,0"/><TextBlockText="{Binding Age}"Margin="5,0,0,0"/></StackPanel><StackPanelOrientation="Horizontal"><TextBlockText="{Binding Address}"Margin="5,0,0,0"/></StackPanel></StackPanel></Border></DataTemplate></Window.Resources><Grid><ListBoxItemsSource="{Binding Source={StaticResource ResourceKey=personList}}"ItemTemplate="{StaticResource ResourceKey=rect}"></ListBox></Grid></Window>

注意这里在调用时应该绑定的是 ItemTemplate 属性。

 

ItemPanelTemplate详解

 

首先我们要知道常见的条目控件有:ListBox,Menu,StatusBar等。

比如拿ListBox来说,ItemBox的ItemPanel其实是一个VisualizingStackPanel,就是说ListBox的每一项的排列方式是遵循StackPanel的

原则,也就是从上到下的排列方式。如果要实现从左到右排列:

<Windowx:Class="WpfApplication1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:sys="clr-namespace:System;assembly=mscorlib"xmlns:src="clr-namespace:WpfApplication1"Title="MainWindow"Height="350"Width="525"><Window.Resources><ObjectDataProviderx:Key="personList"ObjectType="{x:Type src:PersonList}"/><DataTemplatex:Key="rect"><BorderName="border"BorderBrush="Aqua"BorderThickness="1"Padding="5"Margin="5"><StackPanel><StackPanelOrientation="Horizontal"><TextBlockText="{Binding Name}"Margin="5,0,0,0"/><TextBlockText="{Binding Age}"Margin="5,0,0,0"/></StackPanel><StackPanelOrientation="Horizontal"><TextBlockText="{Binding Address}"Margin="5,0,0,0"/></StackPanel></StackPanel></Border></DataTemplate><ItemsPanelTemplatex:Key="items"><StackPanelOrientation="Horizontal"VerticalAlignment="Center"HorizontalAlignment="Center"/></ItemsPanelTemplate></Window.Resources><Grid><ListBoxItemsSource="{Binding Source={StaticResource ResourceKey=personList}}"ItemTemplate="{StaticResource ResourceKey=rect}"ItemsPanel="{StaticResource ResourceKey=items}"></ListBox></Grid></Window>

也就是说,ItemsPanelTemplate可以用来定义集合控件的容器外观。

 

总结

 

1、Template

控件模板,是指整个控件的展示和布局。

如ComboBox,可分为文本区域,下拉按钮区域,Items的Popup区域。

Template就是管理这些位置的布局。

2、ItemsPresenter

可以简单理解为占位符,在样式中使用,标记着这个区域用来展示该控件的Items。

如:ComboBox的下拉列表的可选项。

但是,只负责显示,而不能管理如何显示,如果我们要内容横向排列,就要用到ItemsPanel。

3、ItemsPanel

管理Items的排列方式,如,ComboBox默认是竖直排列的,我们要横着排列,只需要定义ItemsPanel为WrapPanel,就可以了。

这时候Items的排列方式已经完成,如果还要让ComboBox的每个项都重写,比如,背景、图标等,就要用到ItemContainerStyle。

4、ItemContainerStyle

就是每个项的样式,自己重写,就可以定制出每个项的样式了。

以上就是浅谈WPF之各种模板的全部内容。

相关文章
|
7月前
|
C#
2000条你应知的WPF小姿势 基础篇<69-73 WPF Freeze机制和Template>
2000条你应知的WPF小姿势 基础篇<69-73 WPF Freeze机制和Template>
47 0
|
C#
WPF QuickStart系列之样式和模板(Style and Template)
原文:WPF QuickStart系列之样式和模板(Style and Template) 在WPF桌面程序中,当我们想构建一个统一的UI表现时(在不同操作系统下,显示效果一致),此时我们就需要使用到WPF中的样式和模板技术。
995 0
|
C#
WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
原文:WPF - 模板查看工具:Show Me The Template及如何查看第三方主题   在学习WPF的模板(DataTemplate、ItemsPanelTemplate、ControlTemplate)时,经常会想看看WPF内建的控件模板。
1578 0
|
C# 容器
WPF中各个Template的分析(转)
作为新手,还是没看明白本文,留着以后再学习 在使用TabControl、ListView、Menu、TreeView的时候被各种Template搞得头昏眼花,决心把这个问题搞清楚,究竟什么时候该用什么Template?这是个麻烦的问题,欠揍的表达方法是“根据俺这么多年写程序的经验,这是一个需要经验才能解决的问题”。
850 0
|
C#
2000条你应知的WPF小姿势 基础篇<69-73 WPF Freeze机制和Template>
原文:2000条你应知的WPF小姿势 基础篇   在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师。最为出色的是他维护了两个博客:2,000Things You Should Know About C#  和 2,000 Things You Should Know About WPF 。
1282 0
|
6天前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
|
6天前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
69 1
|
9月前
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
499 0
|
9月前
|
C# Windows
WPF技术之RichTextBox控件
WPF RichTextBox是Windows Presentation Foundation (WPF)中提供的一个强大的文本编辑控件,它可以显示富文本格式的文本,支持多种文本处理操作。
363 0
|
6天前
|
前端开发 C# 容器
浅谈WPF之控件拖拽与拖动
使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,简述如何在WPF中实现控件的拖拽和拖动,仅供学习分享使用,如有不足之处,还请指正。
118 2