DataTemplate和ControlTemplate的关系
DataTemplate和ControlTemplate的关系(转载自haiziguo)
一、ContentControl中的DataTemplate
在开始之前,我们先去看一下ContentControl的定义,有两个属性:
public object Content { get; set; }
public DataTemplate ContentTemplate { get; set; }
其特点是只能容纳一个内容,内容类型是object类型,其中Button控件是我们大家比较熟悉且属于ContentControl的类,这里用TextBlock做Content。

这个很正常,因为内容是object的嘛,那么下面我就使用另外一种笔刷作为其内容。看结果:

显示内容成了笔刷转化后的字符串。如果是在回头看看DataTemplate的话,会发现其摘要是:
获取或设置用于显示 System.Windows.Controls.ContentControl 内容的数据模板。内容的数据模板也就是说内容以什么样子表现出来。
下面我就让button的内容-笔刷在一个圆上显示出来。

以上我使用了button内容控件是实现了用圆形来展示button的内容。当然推而广之,我可以使用任何内容控件,先设置其Content(该内容可以是任何复杂的内容),然后使用DataTemplate来表达Content的数据。
UserControl也是一个ContentControl,我们使用一个UserControl控件来实现一个同学的信息:定义一个Student类,然后初始化一个stu,设置其为UC的Content,然后罗列出Content中的数据。

由上面的两个例子可以得出的结论是ContentControl中的DataTemplate是用来表示Content中的数据的。Content属性可以在xaml或者C#中指定。
也就是说Content是DataTemplate的绑定的数据源,具体的表现形式是由DataTemplate决定的。
二、Control的ControlTemplate
在Control中,有个Template属性,其摘要和返回结果如下:
// 摘要:
// 获取或设置控件模板。
// 返回结果:
// 用于定义 System.Windows.Controls.Control 的外观的模板。
public ControlTemplate Template { get; set; }
和DataTemplate不一样的是:该控件定义外观模板。我们还以Button为例子吧。上面返回结果说了是外观的模板,那我想要一个圆角的
Button,应该属于外观的范畴了,很快我想到了使用Border.下面就开工吧。我先弄个按钮,给他写上内容和加上背景颜色:

然后加上Template属性,结果发现背景颜色和内容都没有了。
如
果是按照这样的写法,上面的结果可以看到Content没有abc了。为了显示出来abc我是不是可以在Border里面加个控件TextBlock,然
后在
TextBlock上面写上几个字母,发现可以显示了,但是如果是写的不是abc,还是不能显示abc,说明现在显示的内容的决定于TextBlock,
如果能有一种绑定的话多好呢,我就可以让TextBlock显示的和abc的一致了。有个TemplateBinding,使用时要在
ControlTemplate标签中使用Target。效果如下:

虽然效果实现了,但是有个很严重的问题是我们的Button的Content是object类型,Text是一个字符串类型。如果是button什
么时间心情不好,Content属性变成Image了,那是不是我要跟着“Button”受气呢?为了不受气,想一下有没有使用于所有类型内容的容器呢?
答案是肯定的。使用ContentPresenter。现在无论你是图片还是文字,我都不用鸟你,都有ContentPresenter照着。下面亮出来他的样子

ContentPresenter
非常标准,他会为你自动匹配Target的Content和ContentTemplate。如果Button.Content有关的属性(如
FontSize,Foreground,FontFamily等)发生变化了,不用做任何更改ContentPresenter会帮我们处理的很好,但是如果是和Button本身有关的属性,(如背景色等),需要显式的调整。
三、DataTemplate和ControlTemplate联系
在上面的例子中使用ContentPresenter时,会发现其也有一个ContentTemplate,是不是会猜出来是
DataTemplate类型的,而且是在Template树上"长着"。由此可以猜想ContentTemplate对应的DataTemplate是
Template对应的ControlTemplate树上的一棵子树。为了证明这个事实,下面我还以Button来说明。
现在我分别在button里面使用文字,图片,笔刷作为button的内容,然后添加一个容器来显示Template的子树,下面是xaml代码:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0"
Content="Click to Dump"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="OnButtonClick" />
<Button Grid.Row="0" Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="OnButtonClick">
<Image Source="Images/vs.png"
Stretch="None" />
</Button>
<Button Grid.Row="1" Grid.ColumnSpan="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="OnButtonClick">
<Button.Content>
<RadialGradientBrush>
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="AliceBlue" />
</RadialGradientBrush>
</Button.Content>
<Button.ContentTemplate>
<DataTemplate>
<Ellipse Width="100" Height="100" Fill="{Binding}" />
</DataTemplate>
</Button.ContentTemplate>
</Button>
<ScrollViewer Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
HorizontalScrollBarVisibility="Auto">
<StackPanel Name="stackPanel" />
</ScrollViewer>
</Grid>

我可以根据可视树的查找(VisualTreeHelper类提供的方法结合递归算法)来查看Button中的Template下面都有哪些子树。下面代码是后台代码:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); }
void OnButtonClick(object sender, RoutedEventArgs args)
{
Button btn = sender as Button;
stackPanel.Children.Clear();
DumpVisualTree(btn, );
} void DumpVisualTree(DependencyObject parent, int indent)
{
TextBlock txtblk = new TextBlock();
txtblk.Text = String.Format("{0}{1}", new string(' ', * indent),
parent.GetType().Name);
stackPanel.Children.Add(txtblk); int numChildren = VisualTreeHelper.GetChildrenCount(parent); for (int childIndex = ; childIndex < numChildren; childIndex++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, childIndex);
DumpVisualTree(child, indent + );
}
}
}


分别点击各个按钮,可以看到各个按钮的Template是怎么构造的,有个共同的特点可视树都包含有ContentPresenter,这不正说明 了DataTemplate被ContentPresenter替代掉了,说明的是DataTemplate生成的是ControlTemplate下定义的ContentPresenter以下的树。
四、总结
controltemplate是用来改变控件“本身”的显示的。而控件模板里的控件都是用TemplateBinding去关联控件本身的。举个例子:一个button你用blend打开其模板。会发现button是由一个border和显示内容的控件ContentPresenter组成。ContentPresenter的content是通过TemplateBinding与button的content属性进行关联。datatemplate是用来绑定数据源的。比如一个button,你更改它的datatemplate。里面放一张图片,放一个文本。并且绑定(通过binding)后台数据。
其实说白了,datatemplate是更改controltemplate里ContentPresenter的显示模板的。
源码下载:http://files.cnblogs.com/lzhp/TemlateDemo.zip
DataTemplate和ControlTemplate的关系的更多相关文章
- WPF Template模版之DataTemplate与ControlTemplate的关系和应用【二】
1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它 ...
- 【转】WPF Template模版之DataTemplate与ControlTemplate的关系和应用(二)
1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它 ...
- WPF 基础 - DataTemplate 和 ControlTemplate 的关系和应用
1. 关系 凡是 Template,最后都得作用到 控件 上,这个控件就是 Template 的目标控件(也称模板化控件): DataTemplate 一般是落实在一个 ContentPresente ...
- 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 ...
- [UWP]如何使用代码创建DataTemplate(或者ControlTemplate)
1. 前言 在UWP中DataTemplate是一个十分重要的功能,并且几乎无处不在,例如DataGrid中的DataGridTemplateColumn: <controls:DataGrid ...
- WPF DataTemplate與ControlTemplate
一. 前言 什麼是DataTemplate? 什麼是ControlTemplate? 在stackoverflow有句簡短的解釋 "A DataTemplate, therefore ...
- WPF -- DataTemplate与ControlTemplate结合使用
如深入浅出WPF中的描述,DataTemplate为数据的外衣,ControlTemplate为控件的外衣.ControlTemplate控制控件的样式,DataTemplate控制数据显示的样式,D ...
- DataTemplate和ControlTemplate联系与区别
---恢复内容开始--- 正如标题中的两个拼接的单词所说,DataTemplate就是数据显示的模板,而ControlTemplate是控件自身的模板.(个人理解,错误请指出,谢谢) 我们看这二者在两 ...
随机推荐
- [转载] ffmpeg超详细综合教程——摄像头直播
本文的示例将实现:读取PC摄像头视频数据并以RTMP协议发送为直播流.示例包含了 1.ffmpeg的libavdevice的使用 2.视频解码.编码.推流的基本流程 具有较强的综合性. 要使用liba ...
- Android RemoteViews 11问11答
1.什么是RemoteView? 答:其实就是一种特殊的view结构,这种view 能够跨进程传输.并且这种remoteview 还提供了一些方法 可以跨进程更新界面.具体在android里面 一个是 ...
- IE6对CSS支持Bug收集
1.IE6双外边距 在IE6下,如果对元素设置了浮动,同时又设置了margin-left或者margin-right,margin值会加倍. 例如,设置margin-left:10px在IE6下会显示 ...
- 删除binlog的方法
不知道你有没有为mysql的binlog占用大量磁盘感到无奈,my.cnf里binlog的size可以设置多大做分割,但没有看到删除的配置,在mysql里show了一下variables, mysql ...
- HDU 2151 Worm
Worm Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...
- HDU 5127 Dogs' Candies
Dogs' Candies Time Limit: 30000/30000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others) T ...
- [Everyday Mathematics]20150221
设 $y_n=x_n^2$ 如下归纳定义: $$\bex x_1=\sqrt{5},\quad x_{n+1}=x_n^2-2\ (n=1,2,\cdots). \eex$$ 试求 $\dps{\vl ...
- MongoDB之一介绍(MongoDB与MySQL的区别、BSON与JSON的区别)
MySQL与MongoDB的操作对比,以及区别 MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL ...
- Android圆形图片--ImageView
[ RoundImageView.java ] package com.dxd.roundimageview; import android.content.Context; import andro ...
- 白盒测试之初识gtest工具
因为公司最近对软件产品质量提高了要求,之前项目组中黑盒测试方法就越来越无法满足公司的要求.虽然作为研发,但是也要求对白盒测试有一个系统的了解(毕竟之前没有系统的接触过白盒测试). 单元测试工具有很多种 ...