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,例如下面的代码:

[html] view plaincopy print?
  1. <Window x:Class="WpfApplication11.wnd11421"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="wnd11421" Height="200" Width="300">
  5. <Window.Resources>
  6. <!--ControlTemplate作用在所有目标控件上,Style不能标记x:key-->
  7. <Style TargetType="{x:Type TextBox}">
  8. <Setter Property="Template">
  9. <Setter.Value>
  10. <!--使用TemplateBinding,与模版目标一致-->
  11. <ControlTemplate TargetType="{x:Type TextBox}">
  12. <Border SnapsToDevicePixels="True"
  13. Background="{TemplateBinding Background}"
  14. BorderBrush="{TemplateBinding BorderBrush}"
  15. BorderThickness="{TemplateBinding BorderThickness}"
  16. CornerRadius="5">
  17. <ScrollViewer SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"></ScrollViewer>
  18. </Border>
  19. </ControlTemplate>
  20. </Setter.Value>
  21. </Setter>
  22. <Setter Property="Margin" Value="5"></Setter>
  23. <Setter Property="BorderBrush" Value="Black"></Setter>
  24. <Setter Property="Height" Value="28"></Setter>
  25. </Style>
  26. </Window.Resources>
  27. <StackPanel>
  28. <TextBox></TextBox>
  29. <TextBox></TextBox>
  30. <TextBox Style="{x:Null}"></TextBox>
  31. </StackPanel>
  32. </Window>

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

2.2 应用2

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

[html] view plaincopy print?
  1. <Window x:Class="WpfApplication11.wnd11422"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:local="clr-namespace:WpfApplication11"
  5. Title="wnd11422" Height="200" Width="300">
  6. <Window.Resources>
  7. <!--DataTemplate作用在某个数据类型上,使用DataType,不能设置x:key-->
  8. <DataTemplate DataType="{x:Type local:Unit}">
  9. <Grid>
  10. <StackPanel Orientation="Horizontal">
  11. <Grid>
  12. <Rectangle Fill="Red" Width="{Binding Price}" Stroke="Yellow"></Rectangle>
  13. <TextBlock Text="{Binding Year}"/>
  14. </Grid>
  15. <TextBlock Text="{Binding Price}"></TextBlock>
  16. </StackPanel>
  17. </Grid>
  18. </DataTemplate>
  19. </Window.Resources>
  20. <StackPanel>
  21. <ListBox x:Name="_listBox"></ListBox>
  22. <ComboBox x:Name="_comBox"></ComboBox>
  23. </StackPanel>
  24. </Window>

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

[csharp] view plaincopy print?
  1. /// <summary>
  2. /// DataType
  3. /// </summary>
  4. public class Unit
  5. {
  6. public int Price { get; set; }
  7. public string Year { get; set; }
  8. }

指定数据源:

[csharp] view plaincopy print?
  1. public partial class wnd11422 : Window
  2. {
  3. public wnd11422()
  4. {
  5. InitializeComponent();
  6. List<Unit> _listUnit = new List<Unit>()
  7. {
  8. new Unit(){Price=100, Year="2001" },
  9. new Unit(){Price=120, Year="2002" },
  10. new Unit(){Price=140, Year="2003" },
  11. new Unit(){Price=180, Year="2004" },
  12. new Unit(){Price=150, Year="2005" },
  13. new Unit(){Price=200, Year="2006" },
  14. };
  15. _listBox.ItemsSource = _listUnit;
  16. _comBox.ItemsSource = _listUnit;
  17. }
  18. }

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

2.3 应用3

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

[html] view plaincopy print?
  1. <Window x:Class="WpfApplication11.wnd11423"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="wnd11423" Height="200" Width="300">
  5. <Window.Resources>
  6. <!--Xml中的元素名可以作为DataType-->
  7. <DataTemplate DataType="XUnit">
  8. <Grid>
  9. <StackPanel Orientation="Horizontal">
  10. <Grid>
  11. <Rectangle Fill="Red" Width="{Binding XPath=@Price}" Stroke="Yellow"></Rectangle>
  12. <TextBlock Text="{Binding XPath=@Year}"/>
  13. </Grid>
  14. <TextBlock Text="{Binding XPath=@Price}"></TextBlock>
  15. </StackPanel>
  16. </Grid>
  17. </DataTemplate>
  18. <!--XPath指定一组节点-->
  19. <XmlDataProvider x:Key="ds" XPath="XUnits/XUnit">
  20. <x:XData>
  21. <XUnits xmlns="">
  22. <XUnit Price="100" Year="2001"></XUnit>
  23. <XUnit Price="120" Year="2002"></XUnit>
  24. <XUnit Price="140" Year="2003"></XUnit>
  25. <XUnit Price="180" Year="2004"></XUnit>
  26. <XUnit Price="150" Year="2005"></XUnit>
  27. <XUnit Price="200" Year="2006"></XUnit>
  28. </XUnits>
  29. </x:XData>
  30. </XmlDataProvider>
  31. </Window.Resources>
  32. <StackPanel>
  33. <!--XmlDataProvider使用Binding-->
  34. <ListBox x:Name="_listBox" ItemsSource="{Binding Source={StaticResource ds}}"></ListBox>
  35. <ComboBox x:Name="_comBox" ItemsSource="{Binding Source={StaticResource ds}}"></ComboBox>
  36. </StackPanel>
  37. </Window>

2.4 应用4

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

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

[html] view plaincopy print?
  1. <Window x:Class="WpfApplication11.wnd11424"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="wnd11424" Height="400" Width="300">
  5. <Window.Resources>
  6. <!--年级模版-->
  7. <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
  8. <TextBlock Text="{Binding XPath=@Name}"></TextBlock>
  9. </HierarchicalDataTemplate>
  10. <!--班级模版-->
  11. <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
  12. <RadioButton Content="{Binding XPath=@Name}"></RadioButton>
  13. </HierarchicalDataTemplate>
  14. <!--分组模版-->
  15. <HierarchicalDataTemplate DataType="Group">
  16. <CheckBox Content="{Binding XPath=@Name}"></CheckBox>
  17. </HierarchicalDataTemplate>
  18. <!--数据模版-->
  19. <XmlDataProvider x:Key="ds" XPath="Data/Grade">
  20. <x:XData>
  21. <Data xmlns="">
  22. <Grade Name="一年级">
  23. <Class Name="甲班">
  24. <Group Name="A组"></Group>
  25. <Group Name="B组"></Group>
  26. <Group Name="C组"></Group>
  27. </Class>
  28. <Class Name="乙班">
  29. <Group Name="A组"></Group>
  30. <Group Name="B组"></Group>
  31. <Group Name="C组"></Group>
  32. </Class>
  33. </Grade>
  34. <Grade Name="二年级">
  35. <Class Name="丙班">
  36. <Group Name="A组"></Group>
  37. <Group Name="B组"></Group>
  38. <Group Name="C组"></Group>
  39. </Class>
  40. <Class Name="丁班">
  41. <Group Name="A组"></Group>
  42. <Group Name="B组"></Group>
  43. <Group Name="C组"></Group>
  44. </Class>
  45. </Grade>
  46. </Data>
  47. </x:XData>
  48. </XmlDataProvider>
  49. </Window.Resources>
  50. <!--监听事件-->
  51. <StackPanel MenuItem.Click="StackPanel_Click">
  52. <Menu ItemsSource="{Binding Source={StaticResource ds}}"></Menu>
  53. <TreeView ItemsSource="{Binding Source={StaticResource ds}}" Margin="5"></TreeView>
  54. </StackPanel>
  55. </Window>

事件处理器:

[csharp] view plaincopy print?
  1. private void StackPanel_Click(object sender, RoutedEventArgs e)
  2. {
  3. // Head为XmlElement
  4. XmlElement xmlElem = (e.OriginalSource as MenuItem).Header as XmlElement;
  5. MessageBox.Show(xmlElem.Attributes["Name"].Value);
  6. }

转载于:https://www.cnblogs.com/lizhenlin/p/5906678.html

WPF Template模版之DataTemplate与ControlTemplate的关系和应用【二】相关推荐

  1. DataTemplate和ControlTemplate的关系

    在wp/silverlight/wpf也会经常看到控件模板.经常混淆的应该是DataTemplate和ControlTemplate,本篇文章就来谈谈两件衣服DataTemplate和ControlT ...

  2. WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探

    原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探 最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感觉WPF的开发思 ...

  3. LLBL Gen Pro 3.X 下使用 Template 模版绑定(一)

    LLBL Gen Pro 3.X 下使用 Template 模版绑定(一) 前言 在 LLBL Gen3.X 下已经提供了多种生成模式供用户选择,但是有时候还是需要按照需求来改动 LLBL 生成的代码 ...

  4. wpf template的code写法

    this.Template = XamlReader.Load ("<ControlTemplate xmlns='http://schemas.microsoft.com/clien ...

  5. C++Template 模版的本质

    我想知道上帝的構思,其他的都祇是細節.                                                                                 ...

  6. java 设计模式学习笔记十四 template模版模式

    /**  * 模版  *   * @time 下午09:58:00  * @author retacn yue  * @Email zhenhuayue@sina.com  */ public abs ...

  7. Python框架篇之Django(Template模版:标签tag、自定义filter、extend模板继承)

    文章目录 一.标签的使用(tag) 二.自定义filter和simple_tag 三.extend模板继承 一.标签的使用(tag) 1.语法格式:{% tags %} 2.提供的几种标签 {% if ...

  8. 使用DevExpress WPF主题设计器轻松创建Office 2019绿色主题(二)

    DevExpress WPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序.通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注 ...

  9. WPF+WCF一步一步打造音频聊天室(二):文字聊天和白板共享

    这篇文章将讲述实现WPF的UI和WCF中的双工通信.实现文字部分的聊天功能和实现共享白板的功能. 画WPF的界面其实是一件麻烦的事情.虽然WPF和WindowsForm一样,能将控件拖到哪,它就在哪. ...

最新文章

  1. linux的centos版本修改时间重启后无效的问题
  2. 0b3398php,思想道德修养与法律基础(九江职业技术学院)知到2020题目及答案
  3. chrome 不支持12px以下字体为题的解决
  4. android 动态矩形条,android – 从相机中动态检测不同形状(圆形,方形和矩形)?
  5. ajax url参数中文乱码解决
  6. 『ACM-算法-lowbit』算法竞赛进阶指南--lowbit运算,找到二进制下所有是1的位
  7. Oracle分析函数一——函数列表
  8. 扫地机器人划伤地板_扫地机器人哪个牌子好?会选的才能买到好产品
  9. 【深入理解Java虚拟机学习笔记】第三章 垃圾收集器与内存分配策略
  10. tc275单片机的内核_TC275开发板学习心得(一)
  11. [半监督学习] Combining Labeled and Unlabeled Data with Co-Training
  12. C语言---sprintf组包、sscanf解包
  13. switch内部执行顺序
  14. 安卓Camera一代基于虹软人脸识别程序开发
  15. Java—ISBN号码问题
  16. 专利学习笔记6:在线系统的登录方法
  17. USACO 1.1.4Broken Necklace 破碎的项链
  18. C语言入门——时间换算
  19. DEA入门必备软件推荐--DEARUN
  20. 360欺骗4亿网民 胡乱解读“超级工厂”病毒 ——卡巴斯基关于360胡乱解读“超级工厂”的声明

热门文章

  1. centos7 yum安装docker
  2. Java的List转Scala的数组
  3. Linux 切换目录命令cd
  4. Spring Bean的作用域及生命周期
  5. git 如何取消add操作
  6. 第一行代码学习笔记第二章——探究活动
  7. 平滑均值滤波讲解-Matlab
  8. 8086逻辑运算和移位
  9. 显卡在电脑什么位置_DIY组装电脑教程,新手也能学会自己组装电脑
  10. 理解单片机系统—汇编语言