WPF 基础 - DataTemplate 和 ControlTemplate 的关系和应用
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 的应用
- 设置 key,由需要的控件调用;
- 不设置 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 的关系和应用的更多相关文章
- WPF Template模版之DataTemplate与ControlTemplate的关系和应用【二】
1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它 ...
- 【转】WPF Template模版之DataTemplate与ControlTemplate的关系和应用(二)
1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它 ...
- DataTemplate和ControlTemplate的关系
DataTemplate和ControlTemplate的关系(转载自haiziguo) 一.ContentControl中的DataTemplate 在开始之前,我们先去看一下ContentCont ...
- WPF 基础 - DataTemplate
如果把控件的功能视为内容,则可以使用控件模板 ControlTemplate 来控制它的展现: 如果把数据视为内容,则可以使用数据模板 DataTemplate 把数据展示出来: ControlTem ...
- WPF Template模版之DataTemplate与ControlTemplate【一】
WPF Template模版之DataTemplate与ControlTemplate[一] 标签: Wpf模版 2015-04-19 11:52 510人阅读 评论(0) 收藏 举报 分类: -- ...
- [WPF]如何使用代码创建DataTemplate(或者ControlTemplate)
1. 前言 上一篇文章([UWP]如何使用代码创建DataTemplate(或者ControlTemplate))介绍了在UWP上的情况,这篇文章再稍微介绍在WPF上如何实现. 2. 使用Framew ...
- WPF DataTemplate與ControlTemplate
一. 前言 什麼是DataTemplate? 什麼是ControlTemplate? 在stackoverflow有句簡短的解釋 "A DataTemplate, therefore ...
- WPF -- DataTemplate与ControlTemplate结合使用
如深入浅出WPF中的描述,DataTemplate为数据的外衣,ControlTemplate为控件的外衣.ControlTemplate控制控件的样式,DataTemplate控制数据显示的样式,D ...
- WPF基础到企业应用系列6——布局全接触
本文转自:http://knightswarrior.blog.51cto.com/1792698/365351 一. 摘要 首先很高兴这个系列能得到大家的关注和支持,这段时间一直在研究Windows ...
随机推荐
- Automatic merge failed; fix conflicts and then commit the result.解决方法
产生原因: git pull 的时候会分为两步,第一步先从远程服务器上拉下代码,第二步进行merge.当你merge时候失败了就会产生Automatic merge failed; fix confl ...
- Git使用指南(下)
9 初识分支 把每一次的提交,都用线连起来,你会发现,很连贯. C/C++ 指针的概念 git reset --hard commitid HEAD 如果说内容已经add到暂存区,此时要想 ...
- vue2 响应式细节
data 中的数据是如何处理的? 每一次实例化一个组件,都会调用 initData 然后调用 observe 方法,observe 方法调用了 new Observer(value), 并且返回 __ ...
- 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 ...
- js debounce & throttle All In One
js debounce & throttle All In One debounce & throttle js 节流 防抖 debounce 防抖 防抖,是指一个事件触发后在单位时间 ...
- JavaScript 如何使用 setTimeout 实现 setInterval
JavaScript 如何使用 setTimeout 实现 setInterval website multi content page setIntervalSimulator "use ...
- 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 ...
- TypeScript Generics
TypeScript Generics https://www.typescriptlang.org/docs/handbook/generics.html 泛型 1 Generic Interfac ...
- project config generator
project config generator React, Vue, https://createapp.dev/ parcel https://parceljs.org/ https://git ...
- Flutter: ValueListenableBuilder 内容与ValueListenable保持"同步"的窗口小部件
API 使用这个修改状态可以不用setState(). class _MyHomeState extends State<MyHome> { final ValueNotifier< ...