1. DataTemplate和ControlTemplate的关系

学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它本身长成什么样子(控件内部结构),它的数据会长成什么样子(数据显示结构)都是靠Template生成的。决定控件外观的是ControlTemplate,决定数据外观的是DataTemplate,它们正是Control类的Template和ContentTemplate两个属性值

凡是Template,最终都要作用在控件上,这个控件就是Template的目标控件,也叫模板化控件。你可能会问:DataTemplate的目标应该是数据呀,怎么会是控件呢。DataTemplate给人的感觉的确是施加在数据对象上,但施加在数据对象上生成的一组控件总得有个载体吧?这个载体一般落实在一个叫做ContentPresenter对象上。ContentPresenter类只有ContentTemplate属性、没有Template属性,这就证明了承载由DataTemplate生成的一组控件是他的专门用途。

至此我们可以看出,由ControlTemplate生成的控件树其树根就是ControlTemplate的目标控件,此模板化控件的Template属性值就是一个ControlTemplate实例。与之相仿,由DataTemplate生成的控件其树根是一个ContentPresenter控件,此模板化控件的ContentTemplate属性值就是这个DataTemplate实例。因为ContentPresenter控件是ControlTemplate控件树上的一个节点,所以DataTemplate控件树是ControlTemplate里面的一个子树。

显然,如果把数据对象赋值给ContentPresenter的DataContext属性,由DataTemplate生成的控件自然会找到这个数据对象并把它当作自己的数据源。

2. 应用


2.1 应用1

为Template设置其应用目标有两种方法,一个是逐个设置控件的Template/ContentTemplate/ItemTemlate/CellTemplate等属性,不想应用Template的控件不设置;另一种是整体应用,即把Template应用到某个类型的控件或者数据上。
把ControlTemplate应用到所有控件上需要借助Style来实现,但Style不能标记X:KEY,例如下面的代码:

<Window x:Class="WpfApplication11.wnd11421"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wnd11421" Height="" Width="">
<Window.Resources>
<!--ControlTemplate作用在所有目标控件上,Style不能标记x:key-->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<!--使用TemplateBinding,与模版目标一致-->
<ControlTemplate TargetType="{x:Type TextBox}">
<Border SnapsToDevicePixels="True"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="">
<ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"></ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Margin" Value=""></Setter>
<Setter Property="BorderBrush" Value="Black"></Setter>
<Setter Property="Height" Value=""></Setter>
</Style>
</Window.Resources>
<StackPanel>
<TextBox></TextBox>
<TextBox></TextBox>
<TextBox Style="{x:Null}"></TextBox>
</StackPanel>
</Window>

Style没有X:key标记,默认为引用到所有的x:type指定的控件上,如果不想应用则将style标记为{x:null}。运行效果如下图:

2.2 应用2

把DataTemplate应用到某个数据类型上是设置DataTemplate的DataType属性,并且DataTemplate作为资源时也不能带x:key标记, 例如下面的代码:

<Window x:Class="WpfApplication11.wnd11422"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication11"
Title="wnd11422" Height="" Width="">
<Window.Resources>
<!--DataTemplate作用在某个数据类型上,使用DataType,不能设置x:key-->
<DataTemplate DataType="{x:Type local:Unit}">
<Grid>
<StackPanel Orientation="Horizontal">
<Grid>
<Rectangle Fill="Red" Width="{Binding Price}" Stroke="Yellow"></Rectangle>
<TextBlock Text="{Binding Year}"/>
</Grid>
<TextBlock Text="{Binding Price}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox x:Name="_listBox"></ListBox>
<ComboBox x:Name="_comBox"></ComboBox>
</StackPanel>
</Window>

代码中的DataTemplate的目标数据类型和ListBox的条目类型都是Unit:

/// <summary>
/// DataType
/// </summary>
public class Unit
{
public int Price { get; set; }
public string Year { get; set; }
}

指定数据源:

public partial class wnd11422 : Window
{
public wnd11422()
{
InitializeComponent(); List<Unit> _listUnit = new List<Unit>()
{
new Unit(){Price=, Year="" },
new Unit(){Price=, Year="" },
new Unit(){Price=, Year="" },
new Unit(){Price=, Year="" },
new Unit(){Price=, Year="" },
new Unit(){Price=, Year="" },
}; _listBox.ItemsSource = _listUnit;
_comBox.ItemsSource = _listUnit;
}
}

此时DataTemplate会自动加载到所有的Unit类型对象上,尽管我没有为ListBox和CompBox指定ItemTemplate,一样会得到下图的效果:

2.3 应用3

很多时候数据是以XML形式存取的,如果把XML节点先转换为CLR数据类型再应用DataTemplate就麻烦了。DataTemplate很智能,具有直接把XML数据节点当作目标对象的功能-----XML数据中的元素名(标签名)可以作为DataType,元素的子节点和Attribute可以使用XPath来访问。下面的代码使用XmlDataProvider作为数据源(其XPath指出的必须是一组节点),请注意细节之处的变化,结果和应用2的效果相同:

<Window x:Class="WpfApplication11.wnd11423"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wnd11423" Height="" Width="">
<Window.Resources>
<!--Xml中的元素名可以作为DataType-->
<DataTemplate DataType="XUnit">
<Grid>
<StackPanel Orientation="Horizontal">
<Grid>
<Rectangle Fill="Red" Width="{Binding XPath=@Price}" Stroke="Yellow"></Rectangle>
<TextBlock Text="{Binding XPath=@Year}"/>
</Grid>
<TextBlock Text="{Binding XPath=@Price}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
<!--XPath指定一组节点-->
<XmlDataProvider x:Key="ds" XPath="XUnits/XUnit">
<x:XData>
<XUnits xmlns="">
<XUnit Price="" Year=""></XUnit>
<XUnit Price="" Year=""></XUnit>
<XUnit Price="" Year=""></XUnit>
<XUnit Price="" Year=""></XUnit>
<XUnit Price="" Year=""></XUnit>
<XUnit Price="" Year=""></XUnit>
</XUnits>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<StackPanel>
<!--XmlDataProvider使用Binding-->
<ListBox x:Name="_listBox" ItemsSource="{Binding Source={StaticResource ds}}"></ListBox>
<ComboBox x:Name="_comBox" ItemsSource="{Binding Source={StaticResource ds}}"></ComboBox>
</StackPanel>
</Window>

2.4 应用4

XML的优势就是可以方便的表示带有层级的数据,比如:年级----班级----小组 或  主菜单---次菜单----三级菜单。同时WPF准备了TreeView和MenuItem控件来显示层级数据。能够帮助层级控件显示层级数据的模板是HierachicalDataTemplate。下面是实际工作中常见的例子:

值得一提的是,HierarchicalDataTemplate的作用不是MenuItem的内容而是它的Header。如果对MenuItem的单击事件进行侦听处理,我们就可以从被单击的MenuItem的Header中取出XML数据。

<Window x:Class="WpfApplication11.wnd11424"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wnd11424" Height="" Width="">
<Window.Resources>
<!--年级模版-->
<HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
<TextBlock Text="{Binding XPath=@Name}"></TextBlock>
</HierarchicalDataTemplate>
<!--班级模版-->
<HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
<RadioButton Content="{Binding XPath=@Name}"></RadioButton>
</HierarchicalDataTemplate>
<!--分组模版-->
<HierarchicalDataTemplate DataType="Group">
<CheckBox Content="{Binding XPath=@Name}"></CheckBox>
</HierarchicalDataTemplate> <!--数据模版-->
<XmlDataProvider x:Key="ds" XPath="Data/Grade">
<x:XData>
<Data xmlns="">
<Grade Name="一年级">
<Class Name="甲班">
<Group Name="A组"></Group>
<Group Name="B组"></Group>
<Group Name="C组"></Group>
</Class>
<Class Name="乙班">
<Group Name="A组"></Group>
<Group Name="B组"></Group>
<Group Name="C组"></Group>
</Class>
</Grade>
<Grade Name="二年级">
<Class Name="丙班">
<Group Name="A组"></Group>
<Group Name="B组"></Group>
<Group Name="C组"></Group>
</Class>
<Class Name="丁班">
<Group Name="A组"></Group>
<Group Name="B组"></Group>
<Group Name="C组"></Group>
</Class>
</Grade>
</Data>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<!--监听事件-->
<StackPanel MenuItem.Click="StackPanel_Click">
<Menu ItemsSource="{Binding Source={StaticResource ds}}"></Menu>
<TreeView ItemsSource="{Binding Source={StaticResource ds}}" Margin=""></TreeView>
</StackPanel>
</Window>

事件处理器:

private void StackPanel_Click(object sender, RoutedEventArgs e)
{
// Head为XmlElement
XmlElement xmlElem = (e.OriginalSource as MenuItem).Header as XmlElement;
MessageBox.Show(xmlElem.Attributes["Name"].Value);
}

原文地址:https://www.cnblogs.com/lizhenlin/p/5906678.html

【转】WPF Template模版之DataTemplate与ControlTemplate的关系和应用(二)的更多相关文章

  1. WPF Template模版之DataTemplate与ControlTemplate的关系和应用【二】

    1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它 ...

  2. WPF Template模版之DataTemplate与ControlTemplate【一】

    WPF Template模版之DataTemplate与ControlTemplate[一] 标签: Wpf模版 2015-04-19 11:52 510人阅读 评论(0) 收藏 举报  分类: -- ...

  3. 【转】WPF Template模版之DataTemplate与ControlTemplate(一)

    WPF系统不但支持传统的Winfrom编程的用户界面和用户体验设计,更支持使用专门的设计工具Blend进行专业设计,同时还推出了以模板为核心的新一代设计理念. 1. 模板的内涵 作为表现形式,每个控件 ...

  4. DataTemplate和ControlTemplate的关系

    DataTemplate和ControlTemplate的关系(转载自haiziguo) 一.ContentControl中的DataTemplate 在开始之前,我们先去看一下ContentCont ...

  5. WPF 基础 - DataTemplate 和 ControlTemplate 的关系和应用

    1. 关系 凡是 Template,最后都得作用到 控件 上,这个控件就是 Template 的目标控件(也称模板化控件): DataTemplate 一般是落实在一个 ContentPresente ...

  6. WPF Template模版之寻找失落的控件【三】

    “井水不犯河水”常用来形容两个组织之间界限分明.互不相干,LogicTree与控件内部这颗小树之间就保持着这种关系.换句话说,如果UI元素树上有个X:Name=“TextBox1”的控件,某个控件内部 ...

  7. WPF中UserControl和DataTemplate

    最新更新: http://denghejun.github.io 前言 前言总是留给我说一些无关主题的言论,WPF作为全新Microsoft桌面或web应用程序显示技术框架, 从08年开始,一直到现在 ...

  8. [WPF]如何使用代码创建DataTemplate(或者ControlTemplate)

    1. 前言 上一篇文章([UWP]如何使用代码创建DataTemplate(或者ControlTemplate))介绍了在UWP上的情况,这篇文章再稍微介绍在WPF上如何实现. 2. 使用Framew ...

  9. WPF DataTemplate與ControlTemplate

    一. 前言     什麼是DataTemplate? 什麼是ControlTemplate? 在stackoverflow有句簡短的解釋 "A DataTemplate, therefore ...

随机推荐

  1. [CF1131F] Asya And Kittens

    Description: 给定n个点的序列,一开始有n个块,每次将两个块合并,并告诉你这两个块中的一对元素,求一种可能的原序列 Hint: \(n \le 1.5*10^5\) Solution: 实 ...

  2. python数据类型内置方法 字符串和列表

    1.字符串 内置方法操作# a = 'qqssf'#1. print(a[-1:]) #按索引取,正向从0开始,反向从-1开始# print(len(a)) #取长度# a = 'qqssf'# 2. ...

  3. Flask特殊装饰器

    @app.errorhandler():重定义错误返回信息 @app.errorhandler(404) #监听多少写多少 def error404(message): return f"你 ...

  4. instanceof详解

    instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例: <?php class MyClass { } class NotMyClass { } $a = new ...

  5. yii2 Gridview网格小部件

    Gridview 网格小部件 一.特点: 1.是yii中功能最强大的小部件之一: 2.非常适合快速建立系统的管理后台. 3.用 dataProvider 键来指定数据的提供者 4.用 filterMo ...

  6. selenium3 文件系列之------ opencsv读取csv文件

    最近在学习selenium有关文件的读取测试,今天先总结一下如何读取csv文件.CSV的定义是与逗号分隔的值(Comma-Separated Values),在Java中需要用到第三方lib去处理读取 ...

  7. sqlmap简单使用

    就以实验吧上那个简单的sql注入题为例吧,不过那道题确实经典,把sqlmap的整个使用过程都展现了一遍,先奉上那道题的地址:http://ctf5.shiyanbar.com/web/index_3. ...

  8. api日常总结:前端常用js函数和CSS常用技巧

    我的移动端media html{font-size:10px} @media screen and (min-width:321px) and (max-width:375px){html{font- ...

  9. Office Web Apps 2013 修改Excel在线查看文件大小限制

    前言 最近搭建了一个OWA 2013环境,帮客户实现在线查看Excel文档,不过,使用过程中出现了错误,文件大小超过10MB就无法预览了,查了好久,发现需要使用PowerShell命令进行修改. 1. ...

  10. 最课程阶段大作业06:U度节能平台控制系统

    除了互联网项目,当今社会还有一个概念非常流行,那就是:物联网.什么是物联网?物联网是通过传感设备,按约定的协议,把任意物品与互联网相连接,进行信息交换和通信,以实现智能化识别.定位.跟踪.监控和管理的 ...