深入浅出WPF-11.Template(模板)01
模板
在WPF中,模板可以分为两大类:
控件模板(ControlTemplate)是算法内容的表现形式,一个控件怎么组织其内部的结构才能让它更符合业务逻辑,让用户操作更舒服,都是由她控制的。它决定了控件长什么样子,并让程序员有机会在控件原有的内部逻辑基础上扩展自己的逻辑。
数据模板(DataTemplate)是数据内容的表现形式,一条数据表现成什么样子,是简单的文本还是直观的图形动画就由他决定。
我们先了解一下数据模板,同样一条数据比如拥有类Student实例,具有如下就一个字段:
public class Student
{
/// <summary>
/// 索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 性别
/// </summary>
public Sex Sex { get; set; }
/// <summary>
/// 出生日期
/// </summary>
public DateTime BirthDate { get; set; }
}
/// <summary>
/// 性别
/// </summary>
public enum Sex : byte
{
/// <summary>
/// 男
/// </summary>
Male = 0,
/// <summary>
/// 女
/// </summary>
Female = 1,
/// <summary>
/// 其他
/// </summary>
Other = 2,
}
这样的内容,在不同的控件中展示,展示的形式会不一样,这种模式称之为 数据-视图 模式。在WPF中,我们可以使用自定义控件UserControl来实现,也可以使用数据模板DataTemplate实现。
DataTemplate常用在下面情况下:
- ContentControl的ContentTemplate属性,相当与给ContentControl的内容穿衣服
- ItemsControl 的ItemTemplate属性,相当远给ItemsControl的数据条目穿衣服
- GridViewColumn的CellTemplate属性,相当于给GridViewColumn的单元格的数据穿衣服
我么你先看一下一个程序的展示效果

这里我们看一下代码实现:
<UserControl
x:Class="LpbPrj.Client.Views.ResultWideAreaImagingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:control="clr-namespace:LpbPrj.Client.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:langs="clr-namespace:LpbPrj.Client.Properties.Langs"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/">
<ListBox
Margin="0,0,0,0"
control:CustomeSelectionItems.SelectedItems="{Binding ResultSelectedItems}"
BorderThickness="0"
ItemsPanel="{StaticResource FluidMoveBehaviorWrapPanelItemsPanelTemplate}"
ItemsSource="{Binding ResultList}"
SelectedItem="{Binding Result}"
SelectionMode="{Binding SelectionMode}"
Style="{StaticResource WrapPanelHorizontalListBox}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<ContentControl prism:RegionManager.RegionName="ItemWideAreaImaging" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>
在这个ListBox中,我们对其中的ItemTemplate穿衣服,这个衣服的内容是:
<UserControl
x:Class="LpbPrj.Client.Views.ItemWideAreaImaging"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:langs="clr-namespace:LpbPrj.Client.Properties.Langs"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/">
<hc:Card
MaxWidth="240"
Margin="8"
BorderThickness="0"
Effect="{StaticResource EffectShadow2}"
Footer="{Binding}"
Header="{Binding}">
<hc:Card.HeaderTemplate>
<DataTemplate>
<TextBlock
Margin="5"
Style="{StaticResource TextBlockDefault}"
Text="{Binding ExamType, Converter={StaticResource DtoShowStringConverter}}" />
</DataTemplate>
</hc:Card.HeaderTemplate>
<Border CornerRadius="4,4,0,0" Style="{StaticResource BorderClip}">
<Grid>
<Image Source="{Binding ImageThumbPath, Converter={StaticResource Path2BitmapImageConverter}}" Stretch="Uniform" />
</Grid>
</Border>
<hc:Card.FooterTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
Margin="5"
Orientation="Horizontal">
<TextBlock
Style="{StaticResource TextBlockDefault}"
Text="{Binding ExamFileType, Converter={StaticResource DtoShowStringConverter}}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />
<TextBlock
Margin="10,0,0,0"
Style="{StaticResource TextBlockDefault}"
Text="{Binding ExamImageType, Converter={StaticResource ExamImageTypeConverter}}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />
<TextBlock
Margin="10,0,0,0"
Style="{StaticResource TextBlockDefault}"
Text="{Binding EyeType, Converter={StaticResource DtoShowStringConverter}}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />
</StackPanel>
<CheckBox
Grid.Column="1"
Width="30"
Height="30"
Margin="10,0,5,0"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
</Grid>
</DataTemplate>
</hc:Card.FooterTemplate>
</hc:Card>
</UserControl>
这段代码中的prism,我们暂且不管,但是主要内容还是能够理解的,我们使用了一个Card控件进行描述ListBox的展示内容,每个Card又通过TextBlock和CheckBox等控件进行描述。TextBlock中的对应的数据类型可能不能直接用于展示,比如枚举值,时间类型等。这里我们通过转化Converter来实现想要的展示形式。
这里面存在一个认识的误区,在上面的代码中,我们认为ListBox的Items属性里面存放的是数据而不是控件。我们可以直接将ListBox的选中属性SelectedItem绑定到一个对应的数据实例中。这种模式叫做数据驱动模式。和我们之前使用的事件驱动模式不一样。事件驱动是控件和控件之间沟通或者说是形式和形式之间的沟通,而数据驱动则是数据与控件之间的沟通,是内容和形式之间的沟通。
数据模板理解之后,我们再看一下控件模板ControlTemplate,我们可以使用披着羊皮的狼来理解控件模板,表面上看上去是羊,但是其实是狼。所以控件模板只是改变了控件的外形,不能改变控件的本质。对应控件外形的编辑我们推荐使用Blend。
我们先看一个简单的Lable标签:
<Style x:Key="LabelBaseStyle" TargetType="{x:Type Label}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4" />
</Trigger>
</Style.Triggers>
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background" Value="{DynamicResource RegionBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}" />
<Setter Property="CornerRadius" Value="{StaticResource DefaultCornerRadius}" />
<Setter Property="Padding" Value="{StaticResource DefaultControlPadding}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我们对Lable标签的ControlTemplate进行修改,里面包含了一个控件Border,Border内部包含了控件的内容ContentPresenter。Border的属性通过绑定设置了BorderBrush="{TemplateBinding BorderBrush}" ,代表Border的BorderBrush属性需要绑定到Label的BorderBrush属性,两者保持一致。
深入浅出WPF-11.Template(模板)01的更多相关文章
- 《深入浅出WPF》笔记——模板篇
原文:<深入浅出WPF>笔记--模板篇 我们通常说的模板是用来参照的,同样在WPF中,模板是用来作为制作控件的参照. 一.认识模板 1.1WPF菜鸟看模板 前面的记录有提过,控件主要是算法 ...
- c++11 template 模板练习
直接上代码吧 to do // 111111.cpp: 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> ...
- 《深入浅出WPF》笔记——资源篇
原文:<深入浅出WPF>笔记--资源篇 前面的记录有的地方已经用到了资源,本文就来详细的记录一下WPF中的资源.我们平时的“资源”一词是指“资财之源”,是创造人类社会财富的源泉.在计算机程 ...
- 编译器对C++ 11变参模板(Variadic Template)的函数包扩展实现的差异
编译器对C++ 11变参模板(Variadic Template)的函数包扩展实现的差异 题目挺绕口的.C++ 11的好东西不算太多,但变参模板(Variadic Template)肯定是其中耀眼的一 ...
- 《深入浅出WPF》 学习笔记
<深入浅出WPF> 序言 1. 什么是WPF 2. 为什么要学习WPF 第一章 XAML概览 1. XAML是什么? 2. XAML有哪些优点 第二章 从零起步认识XAML 1. 新 ...
- 微信小程序新闻列表功能(读取文件、template模板使用)
微信小程序新闻列表功能(读取文件.template) 不忘初心,方得始终.初心易得,始终难守. 在之前的项目基础上进行修改,实现读取文件内容作为新闻内容进行展示. 首先,修改 post.wxml 文件 ...
- ArcGIS API for Silverlight代码中使用Template模板
原文:ArcGIS API for Silverlight代码中使用Template模板 在项目开发中,会遇到点选中聚焦闪烁效果,但是因为在使用Symbol的时候,会设置一定的OffSetX和OffS ...
- WPF 详解模板
在WPF中有三大模板 ControlTemplate,ItemsPanelTemplate,DataTemplate.其中ControlTemplate和 ItemsPanelTemplate是控件模 ...
- 【【分享】深入浅出WPF全系列教程及源码
】
因为原书作者的一再要求,在此声明,本书中的部分内容引用了原书名为<深入浅出WPF>的部分内容,假设博文不能满足你现有的学习须要,能够购买正版图书! 本人10月份提出离职,可是交接非常慢,预 ...
- 《深入浅出WPF》笔记——绘画与动画
<深入浅出WPF>笔记——绘画与动画 本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一 ...
随机推荐
- [转]用C++实现插件体系结构
本文讨论一种简单却有效的插件体系结构,它使用C++,动态链接库,基于面向对象编程的思想.首先来看一下使用插件机制能给我们带来哪些方面的好处,从而在适当时候合理的选择使用. 1. 增强代码的透明度与一致 ...
- C语言预处理编译链接各个阶段错误,分阶段的说一下
C语言预处理编译链接各个阶段错误,分阶段的说一下 C语言预处理编译链接各个阶段错误,分阶段的说一下比如指针异常,数组下标越界什么的 我来答 1个回答 #热议# 你觉得这辈子有希望看到996消失 ...
- 【java虚拟机】jvm内存模型
作者:pengjunlee原文链接:https://blog.csdn.net/pengjunlee/article/details/71909239 目录 一.运行时数据区域 1.程序计数器 2.J ...
- java 文件上传(图片上传)
1.FTP工具类 代码如下: package com.taotao.common.utils; import java.io.File; import java.io.FileInputStream; ...
- Oracle基本用法(一)
一.简介 数据库:Oracle数据库的概念和其他数据库不一样,这里的数据库是一个操作系统只有一个库,可以看做Oracle就是一个大的数据库. 实例:一个Oracle实例有一系列的后台进程和内存结构组成 ...
- mzy git学习,撤销修改(二)
git checkout – file: 撤销我们对工作区的修改(没有提交到暂存区) 当我们在工作区修改了之后,并没有提交到暂存区,如果要撤销对 某个文件的修改的话,就使用 git checkout ...
- (int)a、&a、(int)&a、(int&)a的区别,很偏僻的题
(int)a.&a.(int)&a.(int&)a的区别,很偏僻的题 #include <iostream> #include <stdio.h> #i ...
- SSE图像算法优化系列三十一:Base64编码和解码算法的指令集优化。
一.基础原理 Base64是一种用64个Ascii字符来表示任意二进制数据的方法.主要用于将不可打印的字符转换成可打印字符,或者简单的说是将二进制数据编码成Ascii字符.Base64也是网络 ...
- 自己写一个Map
Map的实现其实很简单,一个key对应一个value就行 . 本Map是写着玩的,是想告诉初学者我们也可以写一个简单的Map来自己用 代码: public class MyMap<K, V> ...
- Ansible快速实战指南----多机自动化执行命令、部署神器
1.需求: 需要在多台主机上,发送文件.执行命令,进行快速部署 2.ansible 远程复制文件 例子:在当前节点(20.88.14 ...