WPF系统不但支持传统的Winfrom编程的用户界面和用户体验设计,更支持使用专门的设计工具Blend进行专业设计,同时还推出了以模板为核心的新一代设计理念。

1. 模板的内涵

作为表现形式,每个控件都是为了实现某种用户操作算法和直观显示某种数据而生,一个控件看上去是什么样子由它的“算法内容”和“数据内容"决定,这就是内容决定形式,这里,我们引入两个概念:

控件的算法内容:控件能展示哪些数据、具有哪些方法、能响应哪些操作、能激发什么事件,简而言之就是控件的功能,它们是一组相关的算法逻辑。
控件的数据内容:控件具体展示的数据是什么。

以往的GUI开发技术(ASP.NET+Winform)中,控件内部逻辑和数据是固定的,程序员不能改变;对于控件的外观,程序员能做的改变也非常的有限,一般也就是设置控件的属性,想改变控件的内部结构是不可能的。如果想扩展一个控件的功能或者更改器外观让其更适应业务逻辑,哪怕只是一丁点的改变,也需要创建控件的子类或者创建用户控件。造成这个局面的根本原因是数据和算法的“形式”和“内容”耦合的太紧了。

在WPF中,通过引入模板,微软将数据和算法的内容与形式解耦了。WPF中的Template分为两大类:
ControlTemplate:是算法内容的表现形式,一个控件怎么组织其内部结构才能让它更符合业务逻辑、让用户操作起来更舒服就是由它来控制的。它决定了控件“长成什么样子”,并让程序员有机会在控件原有的内部逻辑基础上扩展自己的逻辑。
DataTemplate:是数据内容的展示方式,一条数据显示成什么样子,是简单的文本还是直观的图形就由它来决定了。

Template就是数据的外衣-----ControlTemplate是控件的外衣,DataTemplate是数据的外衣。

2. 数据的外衣DataTemplate

WPF不但支持UserControl还支持DataTemplate为数据形成视图。不要以为DataTemplate有多难!从UserControl升级到DataTemplate一般就是复制,粘贴一下再改几个字符的事儿。

DataTemplate常用的地方有三处,分别是:
ContentControl的ContentTemplate属性,相当于给ContentControl的内容穿衣服。
ItemsControl的ItemTemplate,相当于给ItemControl的数据条目穿衣服。
GridViewColumn的CellTempldate属性,相当于给GridViewColumn的数据条目穿衣服。

事件驱动是控件和控件之间沟通或者说是形式和形式之间的沟通,数据驱动则是数据与控件之间的沟通,是内容决定形式。使用DataTemplate就可以方便的把事件驱动模式转换为数据驱动模式。

让我们用一个例子体现DataTemplate的使用。例子实现的需求是这样的:有一列汽车数据,这列数据显示在ListBox里面,要求ListBox的条目显示汽车的厂商图标和简要参数,单击某个条目后在窗体的详细内容区显示汽车的图片和详细参数。厂商的Logo和汽车的照片都是要用到的,所以先在项目中建立资源管理目录并把图片添加进来。Logo文件名与厂商的名称一致,照片的名称则与车名一致。组织结构如图:

 

创建Car数据类型:

/// <summary>
/// Car数据类型 -- 必须定义成属性{ get; set; }
/// </summary>
public class Car
{
public string Name { get; set; }
public string ImagePath { get; set; }
public string Automarker { get; set; }
public string Year { get; set; }
}

汽车厂商和名称不能直接拿来作为图片路径,这时就要使用Converter:

/// <summary>
/// 路径转图片
/// </summary>
public class PathToImage:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string url = (string)value;
return(new BitmapImage(new Uri(url, UriKind.Relative)));
} public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

XAML中添加条目模版:

<DataTemplate x:Key="_carListItemViewTemplate">
<Grid Margin="">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Automarker, Converter={StaticResource _path2Image}}" Grid.RowSpan=""
Width="" Height=""></Image>
<StackPanel Margin="5,10">
<TextBlock Text="{Binding Name}" FontSize="" FontWeight="Bold"></TextBlock>
<TextBlock Text="{Binding Year}" FontSize=""></TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>

XAML中添加显示详细信息的模版:

<DataTemplate x:Key="_carDetailViewTemplate">
<Border BorderBrush="Black" BorderThickness="" CornerRadius="">
<StackPanel Margin="">
<Image Width="" Height="" Source="{Binding Path=ImagePath, Converter={StaticResource _path2Image}}"></Image>
<StackPanel Orientation="Horizontal" Margin="5, 0">
<TextBlock Text="Name:" FontWeight="Bold" FontSize=""></TextBlock>
<TextBlock Text="{Binding Path=Name}" FontSize="" Margin="5, 0"></TextBlock>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>

完整的XAML代码:

<Window x:Class="WpfApplication11.wnd112"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication11"
Title="DataTemplate" Height="" Width="">
<Window.Resources>
<!--Convert-->
<local:PathToImage x:Key="_path2Image"></local:PathToImage>
<!--DataTemplate for Detail View -->
<DataTemplate x:Key="_carDetailViewTemplate">
<Border BorderBrush="Black" BorderThickness="" CornerRadius="">
<StackPanel Margin="">
<Image Width="" Height="" Source="{Binding Path=ImagePath, Converter={StaticResource _path2Image}}"></Image>
<StackPanel Orientation="Horizontal" Margin="5, 0">
<TextBlock Text="Name:" FontWeight="Bold" FontSize=""></TextBlock>
<TextBlock Text="{Binding Path=Name}" FontSize="" Margin="5, 0"></TextBlock>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
<!--DataTemplate for Item View -->
<DataTemplate x:Key="_carListItemViewTemplate">
<Grid Margin="">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Automarker, Converter={StaticResource _path2Image}}" Grid.RowSpan=""
Width="" Height=""></Image>
<StackPanel Margin="5,10">
<TextBlock Text="{Binding Name}" FontSize="" FontWeight="Bold"></TextBlock>
<TextBlock Text="{Binding Year}" FontSize=""></TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
<!---Window Content-->
<StackPanel Orientation="Horizontal" Margin="">
<UserControl ContentTemplate="{StaticResource _carDetailViewTemplate}" Content="{Binding Path=SelectedItem, ElementName=_listBoxCars}"></UserControl>
<ListBox x:Name="_listBoxCars" Width="" Margin="5,0" ItemTemplate="{StaticResource _carListItemViewTemplate}"></ListBox>
</StackPanel>
</Window>

代码对于初学者来说有点长但是结构非常简单。其中最重要的有两句:
ContentTemplate="{StaticResource _carDatialViewTemplate}",相当于给一个普通的UserControl穿上了一件外衣、让Car数据以图文并茂的方式展现出来。这件外衣就是x:Key="_carDatialViewTemplate"标记的DataTemplate资源。
ItemTemplate="{StaticResource _listBoxCars}",把每一件数据的外衣交给ListBox,当ListBox的ItemSource被赋值的时候,ListBox就会为每个条目穿上这件外衣。这件外衣是以x:Key="_listBoxCars"标记的DataTemplate资源。
因为不再使用事件驱动,而且为数据穿衣服的事也已经自动完成,所以后台的C#代码就非常的简单。窗体的C#代码就只剩下这些:

/// <summary>
/// wnd112.xaml 的交互逻辑
/// </summary>
public partial class wnd112 : Window
{
List<Car> _carList;
public wnd112()
{
InitializeComponent(); _carList = new List<Car>()
{
new Car(){Name = "Aodi1", ImagePath=@"/Resources/Images/Aodi.jpg", Automarker=@"/Resources/Images/01077_1.png", Year=""},
new Car(){Name = "Aodi2", ImagePath=@"/Resources/Images/Aodi.png", Automarker=@"/Resources/Images/01077_1.png", Year=""},
}; _listBoxCars.ItemsSource = _carList;
}
}

运行程序,效果如下图:

3. 控件的外衣ControlTemplate

每每提到ControlTemplate我都会想到“披着羊皮的狼”这句话-----披上羊皮之后,虽然看上去像只羊,但其行为仍然是匹狼。狼的行为指的是它能吃别的动物、对着满月嚎叫等事情,控件也有自己的行为,比如显示数据、执行方法、激发事件等。控件的行为要靠编程逻辑来实现,所以也可以把控件的行为称为控件的算法内容。举个例子,WPF中的CheckBox与其基类ToggleButton的功能几乎完全一样,但外观差别上却非常的大,这就是更换ControlTemplate的结果。经过更换ControlTemplate,我们不但可以制作披着CheckBox外衣的ToggleButton,还能制作披着温度计外衣的ProgressBar控件。
注意:
实际项目中,ControlTemplate主要有两大用武之地:
通过更换ControlTemplate来更换控件的外观,使之具有更优的用户体验和外观。
借助ControlTemplate,程序员和设计师可以并行工作,程序员可以使用WPF标准控件进行编程,等设计师的工作完成之后,只需要把新的ControlTemplate应用的程序中即可。

ItemsControl具有一个名为ItemsPanel的属性,它的数据类型是ItemsPanelTemplate。ItemsPanelTemplate也是一种控件Template,它的作用是可以让程序员可以控制ItemsControl的条目容器。

举例而言,在我们的印象中ListBox中的条目都是至上而下排列的,如果客户要求我们做一个水平排列的ListBox怎么办呢?WPF之前,我们只能重写控件比较底层的方法和属性,而现在我们只需要调整ListBox的ItemsPanel属性。

<Window x:Class="WpfApplication11.wnd1132"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wnd1132" Height="" Width="">
<Grid>
<ListBox>
<!--条目容器-->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<!--条目元素-->
<TextBlock Text="Allan"></TextBlock>
<TextBlock Text="Allan2"></TextBlock>
<TextBlock Text="Allan3"></TextBlock>
<TextBlock Text="Allan4"></TextBlock>
</ListBox>
</Grid>
</Window>

条目就会包装在一个水平排列的StackPanel中,从而横向排列,如下图所示:

原文地址:https://www.cnblogs.com/lizhenlin/p/5906729.html

【转】WPF Template模版之DataTemplate与ControlTemplate(一)的更多相关文章

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

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

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

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

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

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

  4. WPF Template模版之寻找失落的控件【三】

    “井水不犯河水”常用来形容两个组织之间界限分明.互不相干,LogicTree与控件内部这颗小树之间就保持着这种关系.换句话说,如果UI元素树上有个X:Name=“TextBox1”的控件,某个控件内部 ...

  5. WPF中UserControl和DataTemplate

    最新更新: http://denghejun.github.io 前言 前言总是留给我说一些无关主题的言论,WPF作为全新Microsoft桌面或web应用程序显示技术框架, 从08年开始,一直到现在 ...

  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 基础 - DataTemplate 和 ControlTemplate 的关系和应用

    1. 关系 凡是 Template,最后都得作用到 控件 上,这个控件就是 Template 的目标控件(也称模板化控件): DataTemplate 一般是落实在一个 ContentPresente ...

随机推荐

  1. 通过Obfuscated ssh避免时不时ssh连接不畅的问题【转】

    众所周知的原因,为了能流畅的使用google.使用某些“不存在”的网站,我们一般都是需要通过某些不方便光明正大说明使用用途的技术.比如通过ssh tunnel,这是最简单的,也是用得最多的. 不过,这 ...

  2. 基于socketserver模块并发套接字

    1.基于tcp协议 服务端: import socketserverclass MyHandler(socketserver .BaseRequestHandler ): def handle(sel ...

  3. 给电脑C盘系统盘瘦身的四种方法

    进入后XP时代,又有很多朋友选择了Win 7系统,很多朋友在使用时可能会发现一个问题.电脑刚被买回来时,我们往往都把C盘(系统盘)预留几十个G左右的空间,而且可能装的东西并不是太多,但是磁盘却显示,可 ...

  4. MySQL(七)

    视图 对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情 解决:定义视图 视图本质就是对查询的一个封装 定义视图 create view stuscore as select students.* ...

  5. asp.net缓存 (转)

    原文地址 http://www.cnblogs.com/knowledgesea/archive/2012/07/10/2530436.html 谢谢 一.缓存概念,缓存的好处.类型.         ...

  6. Python基础-修改excel、redis、接口开发、组织代码

    pymysql模块补充内容 1. 游标.description():显示表的字段属性 (什么是游标:游标用于交互式应用,就好比word里的光标一样,要修改某个地方,要先把光标移动到这里) 用好这个方法 ...

  7. 使用pycharm以及用pycharm句子切分调试

    c在D盘建立了个文件夹,然后把segment1.py文件放进去. 然后双击segment1,就自动用pycharm打开了.然后就可以运行和debug.之前最开始的时候我segment1.py文件放桌面 ...

  8. python之名称空间

    1 类名称空间 创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性 而类的良好总属性:数据属性和函数属性 其中类的数据属性是共享给所有对象 print(id(g1.c ...

  9. Vue(十三)自定义指令

    自定义指令 分类:全局指令.局部指令 1. 自定义全局指令 使用全局方法Vue.directive(指令ID,定义对象) 2. 自定义局部指令   <!DOCTYPE html> < ...

  10. django之Ajax初识

    Ajax准么说是用于Javascript与服务器端进行交互的,我们之前呢没有了解ajax也同样可以完成与服务器的交互,那么ajax的优势在哪里?首先ajax是异步交互的也就是说我们基本不会遇到卡顿现象 ...