1. 关系

  • 凡是 Template,最后都得作用到 控件 上,这个控件就是 Template 的目标控件(也称模板化控件);
  • DataTemplate 一般是落实在一个 ContentPresenter 对象上,而 ContentPresenter 类只有 ContentTemplate 属性、没有 Template 属性,这可以说明它的专门用途是承载由 DataTemplate 生成的一组控件;
  • ControlTemplate 生成的控件树其树根是 ControlTemplate 的目标控件,此目标控件的 Template 属性值是这个 ControlTemplate 实例;
  • DataTemplate 生成的控件树其树根是一个 ContentPresenter 控件,此目标控件的 ContentTemplate 属性值是这个 DataTemplate 实例;
  • 因为 ContentPresenter 控件是 ContentTemplate 控件树上的一个结点,所以 DataTemplate 控件树是 ContentTemplate 控件树的一颗子树;
  • 如果由 Template 生成的控件使用了 TemplateBinding 获取属性值,则 TemplateBinding 的数据源就是应用了这个模板的目标控件;
  • 如果把数据对象赋值给 ContentPresenter 的 DataContext 属性,由 DataTemplate 生成的控件自然会找到这个数据对象并把它当做自己的数据源。

简而言之:

typeof(Control.Template) = ControlTemplate

typeof(Control.ContentTemplate) = DateTemplate ∈ ContentPresenter

ContentPresenter.DateContext => Controls(∈ Datemplate).DataContext

2. 应用

2.1 ControlTemplate 的应用

  1. 设置 key,由需要的控件调用;
  2. 不设置 key,统一运用到某个类型的控件。
<Style TargetType="{x:Type TextBox">
<Setter Property="Template">
<Setter.Value>
<ContentPresenter TargetType="{x:Type TextBox}">
...
</ContentPresenter>
</Setter.Value>
</Setter>
</Style> <TextBox />
<TextBox />
<!--如果不需要这个样式,就另行设置 Style 的属性值-->
<TextBox Style="{x:Null}"/>

2.2 DataTemplate 的应用

同理于 ControlTemplate。

2.2.1 DataTemplate 实例

<DataTemplate DataType="{x:Type xx}">
<Grid>
...
</Grid>
</DataTemplate>
xmlns:sys="clr-namespace:System.Collections;assembly=mscorlib"

<DataTemplate DataType="{x:Type local:Unit}">
<Grid>
...
</Grid>
</DataTemplate> <sys:ArrayList x:key="unitList">
<local:Unit Year="2010" Price="100"/>
<local:Unit Year="2011" Price="110"/>
<local:Unit Year="2012" Price="120"/>
</sys:ArrayList> <ListBox ItemsSource="{StaticResource unitList}" /> public Class Unit
{
public string Year { get; set; }
public string Price { get; set; }
}

虽然没有为 ListBox 指定 ItemTemplate,当 DataTemplate 会自动加载到所有 Unit 类型对象上。

2.2.2 把 XML 数据结点当作目标对象

DataTemplate 具有直接把 XML 数据结点当做目标对象的功能;

  • XML 数据中元素名作为 DataType
  • 可使用 XPath 访问元素的 子结点
  • 可使用 XPath 访问元素的 Attribute
  • XPath 可以在 XmlDataProvider 标签中或 Binding 中定义
2.2.2.1 只用 XML 的一层
<Window.Resources>
<XmlDataProvider x:Key="ds" XPath="Units/Unit">
<x:XData>
<Units xmlns="">
<Unit Year="2001" Price="110"/>
<Unit Year="2002" Price="120"/>
<Unit Year="2003" Price="130"/>
<Unit Year="2004" Price="140"/>
</Units>
</x:XData>
</XmlDataProvider> <DataTemplate DataType="Unit">
<Grid>
<StackPanel Orientation="Horizontal">
<Grid>
<Rectangle Fill="LightSalmon" Width="{Binding XPath=@Price}"/>
<TextBlock Text="{Binding XPath=@Year}"/>
</Grid>
<TextBlock Text="{Binding XPath=@Price}"/>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources> <StackPanel>
<ListBox ItemsSource="{Binding Source={StaticResource ds}}" />
<ComboBox ItemsSource="{Binding Source={StaticResource ds}}" Margin="0 10 0 0" />
</StackPanel>
<Window.Resources>
<XmlDataProvider x:Key="ds">
.. <ListBox ItemsSource="{Binding Source={StaticResource ds}, XPath=/Units/Unit}" />
2.2.2.2 支持 HeaderedItemsControl 的 DataTemplate:HierarchicalDataTemplate

HierarchicalDataTemplate 表示支持 System.Windows.Controls.HeaderedItemsControl 的 System.Windows.DataTemplate,例如 System.Windows.Controls.TreeViewItem 或 System.Windows.Controls.MenuItem。

<Window.Resources>
<XmlDataProvider x:Key="ds" XPath="Data/Units">
<x:XData>
<Data xmlns="">
<Units Name="单元组A">
<Unit Name="A 组 A 房">
<Student Name="AA1" Age="16"></Student>
<Student Name="AA2" Age="17"></Student>
<Student Name="AA3" Age="18"></Student>
</Unit>
<Unit Name="A 组 B 房">
<Student Name="AB1" Age="26"></Student>
<Student Name="AB2" Age="27"></Student>
<Student Name="AB3" Age="28"></Student>
</Unit>
</Units>
<Units Name="单元组B">
<Unit Name="B 组 A 房">
<Student Name="BA1" Age="16"></Student>
<Student Name="BA2" Age="17"></Student>
<Student Name="BA3" Age="18"></Student>
</Unit>
<Unit Name="B 组 B 房">
<Student Name="BB1" Age="26"></Student>
<Student Name="BB2" Age="27"></Student>
<Student Name="BB3" Age="28"></Student>
</Unit>
</Units>
</Data>
</x:XData>
</XmlDataProvider>
<HierarchicalDataTemplate DataType="Units" ItemsSource="{Binding XPath=Unit}">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="Unit" ItemsSource="{Binding XPath=Student}">
<RadioButton Content="{Binding XPath=@Name}" GroupName="gn"/>
</HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="Student" ItemsSource="{Binding XPath=bu}">
<CheckBox>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding XPath=@Name}" Margin="0 0 10 0"/>
<TextBlock Text="{Binding XPath=@Age}"/>
</StackPanel>
</CheckBox>
</HierarchicalDataTemplate>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource="{Binding Source={StaticResource ds}}" />
<TreeView ItemsSource="{Binding Source={StaticResource ds}}"></TreeView>
</StackPanel>

ListBox 只展示了两行 单元组A、单元组B;

TreeView 展示了树形结果,展示了 xml 的所有结点

<!--Data.xml-->
<?xml version="1.0" encoding="utf-8" ?>
<Data xmlns="">
<Operation Name="文件" Gesture="F">
<Operation Name="新建" Gesture="N">
<Operation Name="项目" Gesture="Control + P"/>
<Operation Name="网站" Gesture="Control + W"/>
<Operation Name="文档" Gesture="Control + D"/>
</Operation>
<Operation Name="保存" Gesture="S"/>
<Operation Name="打印" Gesture="P"/>
<Operation Name="退出" Gesture="X"/>
</Operation>
<Operation Name="编辑" Gesture="E">
<Operation Name="拷贝" Gesture="Control + C"/>
<Operation Name="剪切" Gesture="Control + X"/>
<Operation Name="粘贴" Gesture="Control + V"/>
</Operation>
</Data> ... <Window.Resources>
<XmlDataProvider x:Key="ds" Source="Data.xml" XPath="Data/Operation"/> <HierarchicalDataTemplate DataType="Operation" ItemsSource="{Binding XPath=Operation}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
<TextBlock Text="{Binding XPath=@Gesture}"/>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<StackPanel MenuItem.Click="StackPanel_Click">
<Menu ItemsSource="{Binding Source={StaticResource ds}}"/>
</StackPanel> private void StackPanel_Click(object sender, RoutedEventArgs e)
{
MenuItem mi = e.OriginalSource as MenuItem; System.Xml.XmlElement xe = mi.Header as System.Xml.XmlElement; string name = xe.Attributes["Name"].Value;
string gesture = xe.Attributes["Gesture"].Value; }

总结:

1)e.Source 是 Menu,e.OriginalSource 是 MenuItem;

2)HierarchicalDataTemplate 的作用目标不是 MenuItem 的内容,而是 MenuItem 的 Header;

3)可以监听 MenuItem 的单击事件,然后从路由参数的 OriginalSource 取出 MenuItem,取出 MenuItem 就能取出属性名为 Header 的值,从而取到某个特性的值;

4)搭配工厂模式,根据点击的 MenuItem 执行对应的操作。

WPF 基础 - DataTemplate 和 ControlTemplate 的关系和应用的更多相关文章

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

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

  2. 【转】WPF Template模版之DataTemplate与ControlTemplate的关系和应用(二)

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

  3. DataTemplate和ControlTemplate的关系

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

  4. WPF 基础 - DataTemplate

    如果把控件的功能视为内容,则可以使用控件模板 ControlTemplate 来控制它的展现: 如果把数据视为内容,则可以使用数据模板 DataTemplate 把数据展示出来: ControlTem ...

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

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

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

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

  7. WPF DataTemplate與ControlTemplate

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

  8. WPF -- DataTemplate与ControlTemplate结合使用

    如深入浅出WPF中的描述,DataTemplate为数据的外衣,ControlTemplate为控件的外衣.ControlTemplate控制控件的样式,DataTemplate控制数据显示的样式,D ...

  9. WPF基础到企业应用系列6——布局全接触

    本文转自:http://knightswarrior.blog.51cto.com/1792698/365351 一. 摘要 首先很高兴这个系列能得到大家的关注和支持,这段时间一直在研究Windows ...

随机推荐

  1. Automatic merge failed; fix conflicts and then commit the result.解决方法

    产生原因: git pull 的时候会分为两步,第一步先从远程服务器上拉下代码,第二步进行merge.当你merge时候失败了就会产生Automatic merge failed; fix confl ...

  2. Git使用指南(下)

    9 初识分支 把每一次的提交,都用线连起来,你会发现,很连贯. C/C++    指针的概念 git reset --hard commitid HEAD    如果说内容已经add到暂存区,此时要想 ...

  3. vue2 响应式细节

    data 中的数据是如何处理的? 每一次实例化一个组件,都会调用 initData 然后调用 observe 方法,observe 方法调用了 new Observer(value), 并且返回 __ ...

  4. Bash on Ubuntu on Windows ( Windows Subsystem for Linux)

    1 #  Bash on ubuntu on Windows http://www.cnblogs.com/anonymous-ufo/p/6143480.html 1 1 如何启用Bash on u ...

  5. js debounce & throttle All In One

    js debounce & throttle All In One debounce & throttle js 节流 防抖 debounce 防抖 防抖,是指一个事件触发后在单位时间 ...

  6. JavaScript 如何使用 setTimeout 实现 setInterval

    JavaScript 如何使用 setTimeout 实现 setInterval website multi content page setIntervalSimulator "use ...

  7. how to copy to clipboard using windows cmd

    how to copy to clipboard using windows cmd Windows clipboard command line https://www.labnol.org/sof ...

  8. TypeScript Generics

    TypeScript Generics https://www.typescriptlang.org/docs/handbook/generics.html 泛型 1 Generic Interfac ...

  9. project config generator

    project config generator React, Vue, https://createapp.dev/ parcel https://parceljs.org/ https://git ...

  10. Flutter: ValueListenableBuilder 内容与ValueListenable保持"同步"的窗口小部件

    API 使用这个修改状态可以不用setState(). class _MyHomeState extends State<MyHome> { final ValueNotifier< ...