WPF Template模版之DataTemplate与ControlTemplate的关系和应用【二】
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="200" Width="300">
- <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="5">
- <ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"></ScrollViewer>
- </Border>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- <Setter Property="Margin" Value="5"></Setter>
- <Setter Property="BorderBrush" Value="Black"></Setter>
- <Setter Property="Height" Value="28"></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="200" Width="300">
- <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=100, Year="2001" },
- new Unit(){Price=120, Year="2002" },
- new Unit(){Price=140, Year="2003" },
- new Unit(){Price=180, Year="2004" },
- new Unit(){Price=150, Year="2005" },
- new Unit(){Price=200, Year="2006" },
- };
- _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="200" Width="300">
- <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="100" Year="2001"></XUnit>
- <XUnit Price="120" Year="2002"></XUnit>
- <XUnit Price="140" Year="2003"></XUnit>
- <XUnit Price="180" Year="2004"></XUnit>
- <XUnit Price="150" Year="2005"></XUnit>
- <XUnit Price="200" Year="2006"></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="400" Width="300">
- <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="5"></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);
- }
WPF Template模版之DataTemplate与ControlTemplate的关系和应用【二】的更多相关文章
- 【转】WPF Template模版之DataTemplate与ControlTemplate的关系和应用(二)
1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它 ...
- WPF Template模版之DataTemplate与ControlTemplate【一】
WPF Template模版之DataTemplate与ControlTemplate[一] 标签: Wpf模版 2015-04-19 11:52 510人阅读 评论(0) 收藏 举报 分类: -- ...
- 【转】WPF Template模版之DataTemplate与ControlTemplate(一)
WPF系统不但支持传统的Winfrom编程的用户界面和用户体验设计,更支持使用专门的设计工具Blend进行专业设计,同时还推出了以模板为核心的新一代设计理念. 1. 模板的内涵 作为表现形式,每个控件 ...
- DataTemplate和ControlTemplate的关系
DataTemplate和ControlTemplate的关系(转载自haiziguo) 一.ContentControl中的DataTemplate 在开始之前,我们先去看一下ContentCont ...
- WPF 基础 - DataTemplate 和 ControlTemplate 的关系和应用
1. 关系 凡是 Template,最后都得作用到 控件 上,这个控件就是 Template 的目标控件(也称模板化控件): DataTemplate 一般是落实在一个 ContentPresente ...
- WPF Template模版之寻找失落的控件【三】
“井水不犯河水”常用来形容两个组织之间界限分明.互不相干,LogicTree与控件内部这颗小树之间就保持着这种关系.换句话说,如果UI元素树上有个X:Name=“TextBox1”的控件,某个控件内部 ...
- WPF中UserControl和DataTemplate
最新更新: http://denghejun.github.io 前言 前言总是留给我说一些无关主题的言论,WPF作为全新Microsoft桌面或web应用程序显示技术框架, 从08年开始,一直到现在 ...
- [WPF]如何使用代码创建DataTemplate(或者ControlTemplate)
1. 前言 上一篇文章([UWP]如何使用代码创建DataTemplate(或者ControlTemplate))介绍了在UWP上的情况,这篇文章再稍微介绍在WPF上如何实现. 2. 使用Framew ...
- WPF DataTemplate與ControlTemplate
一. 前言 什麼是DataTemplate? 什麼是ControlTemplate? 在stackoverflow有句簡短的解釋 "A DataTemplate, therefore ...
随机推荐
- OpenLayer
<html> <head> <meta charset="utf-8"> <title>GIS开发样例-V1.0</title ...
- MySQL(2)-数据类型和Schema
一.数据类型 只介绍基本的数据类型. MySQL中选择合适的数据类型还是很有必要的,下面是一些通用原则: 小的就是好的 一般情况下,应该尽量使用可以正确存储数据的最小数据类型.更小的数据类型通常更快, ...
- .Net Core Session验证码
1.验证码帮助类 namespace IdeaCore.Services.Common { public class ValidateCodeService : IValidateCodeServic ...
- [ An Ac a Day ^_^ ] CodeForces 691F Couple Cover 花式暴力
Couple Cover Time Limit: 3000MS Memory Limit: 524288KB 64bit IO Format: %I64d & %I64u Descri ...
- UVA 624 CD (01背包)
//路径记录方法:若是dp[j-value[i]]+value[i]>dp[j]说明拿了这个东西,标志为1, //for循环标志,发现是1,就打印出来,并把背包的容量减少,再在次容量中寻找标志: ...
- 创建 .gitignore 文件过滤规
文件 .gitignore 的格式规范如下: 所有空行或者以注释符号 # 开头的行都会被 Git 忽略. 可以使用标准的 glob 模式匹配. 匹配模式最后跟反斜杠(/)说明要忽略的是目录. 要忽略指 ...
- 第三次冲刺spring会议(第一次会议)
[例会时间]2014/5/20 21:15 [例会地点]9#446 [例会形式]轮流发言 [例会主持]马翔 [例会记录]兰梦 小组成员:兰梦 ,马翔,李金吉,赵天,胡佳
- 高精度运算专题-输出函数与字符串转数字函数(Output function and the string to number function)
输出函数:这个函数别看它小,但浓缩的都是精华啊 作用:对于高精度的数组进行倒序输出 思路:首先从被传入的数组第一位开始,一直往前扫输出就可以了(i--) 注释:因为每个数组的第一位是用来存储这个数组的 ...
- Openjudge-计算概论(A)-鸡尾酒疗法
描述: 鸡尾酒疗法,原指“高效抗逆转录病毒治疗”(HAART),由美籍华裔科学家何大一于1996年提出,是通过三种或三种以上的抗病毒药物联合使用来治疗艾 滋病.该疗法的应用可以减少单一用药产生的抗药性 ...
- python--zeros函数和ones函数
使用numpy.zeros,numpy.ones,numpy.eye等方法可以构造特定的矩阵 例如: 代码如下: >>>from numpy import * >>> ...