WPF Template模版之DataTemplate与ControlTemplate【一】

WPF Template模版之DataTemplate与ControlTemplate【一】

标签: Wpf模版

2015-04-19 11:52 510人阅读 评论(0) 收藏 举报

 分类:

-------1.5 .NET(25) 

版权声明:本文为博主郎涯工作室原创文章,未经博主允许不得转载。

目录(?)[+]

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数据类型:

[csharp] view plain copy

print?

  1. /// <summary>
  2. /// Car数据类型 -- 必须定义成属性{ get; set; }
  3. /// </summary>
  4. public class Car
  5. {
  6. public string Name { get; set; }
  7. public string ImagePath { get; set; }
  8. public string Automarker { get; set; }
  9. public string Year { get; set; }
  10. }

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

[csharp] view plain copy

print?

  1. /// <summary>
  2. /// 路径转图片
  3. /// </summary>
  4. public class PathToImage:IValueConverter
  5. {
  6. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  7. {
  8. string url = (string)value;
  9. return(new BitmapImage(new Uri(url, UriKind.Relative)));
  10. }
  11. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  12. {
  13. throw new NotImplementedException();
  14. }
  15. }

XAML中添加条目模版:

[html] view plain copy

print?

  1. <DataTemplate x:Key="_carListItemViewTemplate">
  2. <Grid Margin="2">
  3. <StackPanel Orientation="Horizontal">
  4. <Image Source="{Binding Path=Automarker, Converter={StaticResource _path2Image}}" Grid.RowSpan="3"
  5. Width="64" Height="64"></Image>
  6. <StackPanel Margin="5,10">
  7. <TextBlock Text="{Binding Name}" FontSize="16" FontWeight="Bold"></TextBlock>
  8. <TextBlock Text="{Binding Year}" FontSize="14"></TextBlock>
  9. </StackPanel>
  10. </StackPanel>
  11. </Grid>
  12. </DataTemplate>

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

[html] view plain copy

print?

  1. <DataTemplate x:Key="_carDetailViewTemplate">
  2. <Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
  3. <StackPanel Margin="5">
  4. <Image Width="400" Height="250" Source="{Binding Path=ImagePath, Converter={StaticResource _path2Image}}"></Image>
  5. <StackPanel Orientation="Horizontal" Margin="5, 0">
  6. <TextBlock Text="Name:" FontWeight="Bold" FontSize="20"></TextBlock>
  7. <TextBlock Text="{Binding Path=Name}" FontSize="20" Margin="5, 0"></TextBlock>
  8. </StackPanel>
  9. </StackPanel>
  10. </Border>
  11. </DataTemplate>

完整的XAML代码:

[html] view plain copy

print?

  1. <Window x:Class="WpfApplication11.wnd112"
  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="DataTemplate" Height="350" Width="623">
  6. <Window.Resources>
  7. <!--Convert-->
  8. <local:PathToImage x:Key="_path2Image"></local:PathToImage>
  9. <!--DataTemplate for Detail View -->
  10. <DataTemplate x:Key="_carDetailViewTemplate">
  11. <Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
  12. <StackPanel Margin="5">
  13. <Image Width="400" Height="250" Source="{Binding Path=ImagePath, Converter={StaticResource _path2Image}}"></Image>
  14. <StackPanel Orientation="Horizontal" Margin="5, 0">
  15. <TextBlock Text="Name:" FontWeight="Bold" FontSize="20"></TextBlock>
  16. <TextBlock Text="{Binding Path=Name}" FontSize="20" Margin="5, 0"></TextBlock>
  17. </StackPanel>
  18. </StackPanel>
  19. </Border>
  20. </DataTemplate>
  21. <!--DataTemplate for Item View -->
  22. <DataTemplate x:Key="_carListItemViewTemplate">
  23. <Grid Margin="2">
  24. <StackPanel Orientation="Horizontal">
  25. <Image Source="{Binding Path=Automarker, Converter={StaticResource _path2Image}}" Grid.RowSpan="3"
  26. Width="64" Height="64"></Image>
  27. <StackPanel Margin="5,10">
  28. <TextBlock Text="{Binding Name}" FontSize="16" FontWeight="Bold"></TextBlock>
  29. <TextBlock Text="{Binding Year}" FontSize="14"></TextBlock>
  30. </StackPanel>
  31. </StackPanel>
  32. </Grid>
  33. </DataTemplate>
  34. </Window.Resources>
  35. <!---Window Content-->
  36. <StackPanel Orientation="Horizontal" Margin="5">
  37. <UserControl ContentTemplate="{StaticResource _carDetailViewTemplate}" Content="{Binding Path=SelectedItem, ElementName=_listBoxCars}"></UserControl>
  38. <ListBox x:Name="_listBoxCars" Width="180" Margin="5,0" ItemTemplate="{StaticResource _carListItemViewTemplate}"></ListBox>
  39. </StackPanel>
  40. </Window>

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

[csharp] view plain copy

print?

  1. /// <summary>
  2. /// wnd112.xaml 的交互逻辑
  3. /// </summary>
  4. public partial class wnd112 : Window
  5. {
  6. List<Car> _carList;
  7. public wnd112()
  8. {
  9. InitializeComponent();
  10. _carList = new List<Car>()
  11. {
  12. new Car(){Name = "Aodi1", [email protected]"/Resources/Images/Aodi.jpg", [email protected]"/Resources/Images/01077_1.png", Year="1990"},
  13. new Car(){Name = "Aodi2", [email protected]"/Resources/Images/Aodi.png", [email protected]"/Resources/Images/01077_1.png", Year="2001"},
  14. };
  15. _listBoxCars.ItemsSource = _carList;
  16. }
  17. }

运行程序,效果如下图:

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属性。

[html] view plain copy

print?

  1. <Window x:Class="WpfApplication11.wnd1132"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="wnd1132" Height="80" Width="300">
  5. <Grid>
  6. <ListBox>
  7. <!--条目容器-->
  8. <ListBox.ItemsPanel>
  9. <ItemsPanelTemplate>
  10. <StackPanel Orientation="Horizontal"></StackPanel>
  11. </ItemsPanelTemplate>
  12. </ListBox.ItemsPanel>
  13. <!--条目元素-->
  14. <TextBlock Text="Allan"></TextBlock>
  15. <TextBlock Text="Allan2"></TextBlock>
  16. <TextBlock Text="Allan3"></TextBlock>
  17. <TextBlock Text="Allan4"></TextBlock>
  18. </ListBox>
  19. </Grid>
  20. </Window>

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

时间: 2024-11-03 05:30:46

WPF Template模版之DataTemplate与ControlTemplate【一】的相关文章

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

1. DataTemplate和ControlTemplate的关系 学习过DataTemplate和ControlTemplate,你应该已经体会到,控件只是数据的行为和载体,是个抽象的概念,至于它本身长成什么样子(控件内部结构),它的数据会长成什么样子(数据显示结构)都是靠Template生成的.决定控件外观的是ControlTemplate,决定数据外观的是DataTemplate,它们正是Control类的Template和ContentTemplate两个属性值 凡是Template,

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

“井水不犯河水”常用来形容两个组织之间界限分明.互不相干,LogicTree与控件内部这颗小树之间就保持着这种关系.换句话说,如果UI元素树上有个X:Name=“TextBox1”的控件,某个控件内部也是由Template生成的x:Name="TextBox1"的控件,它们并不冲突,LogicTree不会看到控件内部的细节,控件内部元素也不会去理会控件外面是什么值.你可能会想:“这样一来,万一我想从控件外部访问内部的控件,获取它的属性值,岂不是做不到了.”放心,WPF为我们准备了访问控

WPF Template模版之Style【四】

Style直译过来就是"风格","样式".拿人来举例,人的风格指静态的外观和行为举止.同样一个人,如果留平头.穿上足球队的队服.脚蹬战靴,看上去就是一名叱咤球场的运动员:如果让他换一身笔挺的西装.穿上皮靴.再拎上一个公文包,看上去就是一个商务人士.除了从静态外观来判断一个人的风格,我们还会观察他的行为特点.比如遇到困难时,有些人很乐观,照样谈笑风生.有些人很谨慎.仔细分析问题:有些人很悲观.成天哀声叹气,这就是行为风格,行为风格是由外界刺激的反应体现出来的.说到这儿

DataTemplate和ControlTemplate的关系

在wp/silverlight/wpf也会经常看到控件模板.经常混淆的应该是DataTemplate和ControlTemplate,本篇文章就来谈谈两件衣服DataTemplate和ControlTemplate的关系.本篇文章主要会以wpf控件为主,以便最后的源码大家都可以打开. 一.ContentControl中的DataTemplate 在开始之前,我们先去看一下ContentControl的定义,无论在wp还是在wpf中其都有下面两个属性: public object Content

WPF的模版

此例子来自<深入浅出WPF>,刘铁猛. VS2010 源码1:不使用Bingding 源码2:使用Binding 下面展示一些代码: 主窗体XAML代码: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsof

[UWP]如何使用代码创建DataTemplate(或者ControlTemplate)

原文:[UWP]如何使用代码创建DataTemplate(或者ControlTemplate) 1. 前言 在UWP中DataTemplate是一个十分重要的功能,并且几乎无处不在,例如DataGrid中的DataGridTemplateColumn: <controls:DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Vert

WPF Template

ControlTemplate ControlTemplate:用于定义控件的结构和外观,这样可以将控件外观与控件功能分离开. 在xaml中ControlTemplate通常配置到Style中,通过Style控制控件的结构和外观 如果控件继承自ContentControl类,其模板将包含一个ContentPresenter类成员,ContentPresenter用于指定添加内容的位置,下面是一个Button Style,ContentPresenter的标记表明Button的Content应在G

DataTemplate和ControlTemplate联系与区别

---恢复内容开始--- 正如标题中的两个拼接的单词所说,DataTemplate就是数据显示的模板,而ControlTemplate是控件自身的模板.(个人理解,错误请指出,谢谢) 我们看这二者在两类不同的控件中如何使用: 一:ItemsControl 我们可以利用ControlTemplate来设置控件外表,用DataTemplate来填充控件内容. <Page.Resources> <DataTemplate x:Key="dataTemplate"> &

.NET: WPF Template

Data Template: 要做一个listBox,里面有车子的简单信息,点了里面的item后就会显示详细信息. car class: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace WpfApplication1 8 { 9 public class Car 10