浅谈WPF之各种Template

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

概述

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

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

模板与控件之间的关系

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

通过上图可以看出:

  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,我们可以定制这个触发器列表来使控件对外界的刺激发生反应,比如鼠标经过时文本变成粗体等。

控件模板示例

<Window x: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><ControlTemplate x:Key="rect" TargetType="{x:Type CheckBox}"><ControlTemplate.Resources><SolidColorBrush x:Key="redBrush" Color="Red"/></ControlTemplate.Resources><StackPanel><Rectangle Name="breakRectangle" Stroke="Red" StrokeThickness="2" Width="20" Height="20"><Rectangle.Fill><SolidColorBrush Color="White"/></Rectangle.Fill></Rectangle><ContentPresenter/></StackPanel><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Setter TargetName="breakRectangle" Property="Fill" Value="{StaticResource ResourceKey=redBrush}"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Window.Resources><Canvas><CheckBox Template="{StaticResource ResourceKey=rect}"  Content="我是CheckBox"/></Canvas>
</Window>

 

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

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

<Style x:Key="cbx" TargetType="{x:Type CheckBox}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type CheckBox}"><ControlTemplate.Resources><SolidColorBrush x:Key="redBrush" Color="Red"/></ControlTemplate.Resources><StackPanel><Rectangle Name="breakRectangle" Stroke="Red" StrokeThickness="2" Width="20" Height="20"><Rectangle.Fill><SolidColorBrush Color="White"/></Rectangle.Fill></Rectangle><ContentPresenter/></StackPanel><ControlTemplate.Triggers><Trigger Property="IsChecked" Value="True"><Setter TargetName="breakRectangle" Property="Fill" Value="{StaticResource ResourceKey=redBrush}"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style>

 

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

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

 

c)ItemsPresenter

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

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

<Style x:Key="{x:Type ItemsControl}" TargetType="{x:Type ItemsControl}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ItemsControl}"><Border Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"Padding="{TemplateBinding Padding}"SnapsToDevicePixels="true"><ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/></Border></ControlTemplate></Setter.Value></Setter>
</Style>

 

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

DataTemplate数据模板详解

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

<Window x: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><ObjectDataProvider x:Key="personList" ObjectType="{x:Type src:PersonList}"/><DataTemplate x:Key="rect"><Border Name="border" BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5"><StackPanel><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}" Margin="5,0,0,0"/><TextBlock Text="{Binding Age}" Margin="5,0,0,0"/></StackPanel><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Address}" Margin="5,0,0,0"/></StackPanel></StackPanel></Border></DataTemplate></Window.Resources><Grid><ListBox ItemsSource="{Binding Source={StaticResource ResourceKey=personList}}"ItemTemplate="{StaticResource ResourceKey=rect}"></ListBox></Grid>
</Window>

 

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

ItemsPanelTemplate详解

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

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

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

<Window x: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><ObjectDataProvider x:Key="personList" ObjectType="{x:Type src:PersonList}"/><DataTemplate x:Key="rect"><Border Name="border" BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5"><StackPanel><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}" Margin="5,0,0,0"/><TextBlock Text="{Binding Age}" Margin="5,0,0,0"/></StackPanel><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Address}" Margin="5,0,0,0"/></StackPanel></StackPanel></Border></DataTemplate><ItemsPanelTemplate x:Key="items"><StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"/></ItemsPanelTemplate></Window.Resources><Grid><ListBox ItemsSource="{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之各种模板的全部内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/209008.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【每日OJ —— 622. 设计循环队列】

每日OJ —— 622. 设计循环队列 1.题目&#xff1a;622. 设计循环队列2.解法2.1.解法讲解2.1.1.算法讲解2.1.2.代码实现2.1.3.提交通过展示 1.题目&#xff1a;622. 设计循环队列 2.解法 1.本题有很多解法&#xff1a;可以使用数组&#xff0c;单链表&#xff0c;双链表&#x…

Modbus TCP

Modbus &#xff08;&#x1f446; 百度百科&#xff0c;放心跳转&#xff09; 起源 Modbus 由 Modicon 公司于 1979 年开发&#xff0c;是一种工业现场总线协议标准。 Modbus 通信协议具有多个变种&#xff0c;支持串口&#xff0c;以太网多个版本&#xff0c;其中最著名的…

【每日OJ —— 20.有效的括号(栈)】

每日OJ —— 20.有效的括号&#xff08;栈&#xff09; 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09;2.方法讲解2.1.解法2.1.1.算法讲解2.1.2.代码实现2.1.3.提交通过展示 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09; 2.方法讲解 2.1.解法 利用…

Bean基本注解开发

Commponent 使用Component注解代替<bean>标签 <!--注解扫描:扫描指定的基本包及其子包下的类&#xff0c;识别使用了Component注解的文件--><context:component-scan base-package"org.xfy"></context:component-scan> package org.xfy.Dao.…

PHP中间件实现

目录 1、简单中间实现 2、使用闭包函数实现中间件 在PHP中&#xff0c;中间件是一种常用的设计模式&#xff0c;用于处理请求和响应&#xff0c;它可以在请求到达目标处理程序之前或响应发送给客户端之前执行一些特定的逻辑。中间件提供了一种灵活的方式来修改或扩展应用程序的…

初识JVM(简单易懂),解开JVM神秘的面纱

目录 一、什么是JVM&#xff08;Java虚拟机&#xff09;&#xff1f; 二、JVM的功能 三、JVM的功能-即时编译 四、常见的JVM 五、JVM的组成 五、JVM的工作流程 参考资料 一、什么是JVM&#xff08;Java虚拟机&#xff09;&#xff1f; 在Java的世界里&#xff0c;Java虚…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【如何学习Python自动化测试】—— 多层窗口定位

6 、 多层窗口定位 多层窗口指的是在操作系统图形界面中&#xff0c;一个窗口被另一个窗口覆盖的情况。在多层窗口中&#xff0c;如何定位需要操作的窗口&#xff1f; 一种常见的方法是使用操作系统提供的AltTab快捷键&#xff0c;可以在打开的所有窗口中快速切换焦点。如果需要…

RT-Thread 线程间同步【信号量、互斥量、事件集】

线程间同步 一、信号量1. 创建信号量2. 获取信号量3. 释放信号量4. 删除信号量5. 代码示例 二、互斥量1. 创建互斥量2. 获取互斥量3. 释放互斥量4. 删除互斥量5. 代码示例 三、事件集1. 创建事件集2. 发送事件3. 接收事件4. 删除事件集5. 代码示例 简单来说&#xff0c;同步就是…

Spark---集群搭建

Standalone集群搭建与Spark on Yarn配置 1、Standalone Standalone集群是Spark自带的资源调度框架&#xff0c;支持分布式搭建&#xff0c;这里建议搭建Standalone节点数为3台&#xff0c;1台master节点&#xff0c;2台worker节点&#xff0c;这虚拟机中每台节点的内存至少给…

控制论与科学方法论

《控制论与科学方法论》&#xff0c;真心推荐。 书籍原文电子版PDF&#xff1a;https://pan.quark.cn/s/aa40d59295df&#xff08;分类在学习目录下&#xff09; 备用链接&#xff1a;https://pan.xunlei.com/s/VNgj2vjW-Hf_543R2K8kbaifA1?pwd2sap# 控制论是一种让系统按照我…