引言

书接上回[WPF系列-数据邦定之DataTemplate],本篇介绍如何根据属性切换模板(DataTemplate)

 

切换模板的两种方式:

 

  • 使用DataTemplateSelector来切换模板
  • 使用DataTrigger来实现模板切换。
  • 使用Style来是实现模板切换

 

A DataTemplateSelector does not respond to PropertyChange notifications, so it doesn't get re-evaluated when your properties change.

The alternative I use is DataTriggers that changes the Template based on a property.

For example, this will draw all TaskModel objects using a ContentControl, and the ContentControl.Template is based on the TaskStatus property of the TaskModel

 

 

 

使用DataTemplateSelector切换模板

在 DataType 属性一节中,我们讨论了您可以针对不同的数据对象定义不同的数据模板。 这在您拥有不同类型的 CompositeCollection 或不同类型的项集合时尤其有用。 在使用 DataTrigger 来应用属性值一节中,我们演示了如果您拥有相同类型的数据对象集合,您可以创建 DataTemplate,然后根据每个数据对象的属性值使用触发器来应用更改。 虽然触发器允许您应用属性值或启动动画,但是它们无法让您灵活重构数据对象的结构。 在某些情况下,可能需要您为类型相同但属性不同的数据对象创建其他 DataTemplate。
例如,当 Task 对象的 Priority 值为 1 时,您可能需要为它指定完全不同的外观,以给予您自己一个提醒。 在这种情况下,您需要创建 DataTemplate 来显示高优先级的 Task 对象。 让我们将以下 DataTemplate 添加到资源部分:

<DataTemplate x:Key="importantTaskTemplate">
<DataTemplate.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20"/>
</Style>
</DataTemplate.Resources>
<Border Name="border" BorderBrush="Red" BorderThickness="1"
Padding="5" Margin="5">
<DockPanel HorizontalAlignment="Center">
<TextBlock Text="{Binding Path=Description}" />
<TextBlock>!</TextBlock>
</DockPanel>
</Border>
</DataTemplate>

 

请注意,此示例使用 DataTemplate.Resources 属性。 DataTemplate 中的元素共享该部分中定义的资源。

若要提供逻辑以根据数据对象的 Priority 值选择要使用的 DataTemplate,需要创建 DataTemplateSelector 的子类并重写 SelectTemplate 方法。 在下面的示例中,SelectTemplate 方法提供逻辑以根据 Priority 属性的值返回适当的模板。 可以在封装 Window 元素的资源中找到要返回的模板。

 

using System.Windows;
using System.Windows.Controls; namespace SDKSample
{
public class TaskListDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate
SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement; if (element != null && item != null && item is Task)
{
Task taskitem = item as Task; if (taskitem.Priority == 1)
return
element.FindResource("importantTaskTemplate") as DataTemplate;
else
return
element.FindResource("myTaskTemplate") as DataTemplate;
} return null;
}
}
}

然后,我们可以将 TaskListDataTemplateSelector 声明为资源:

<Window.Resources>

...

<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>

...

</Window.Resources>

若要使用模板选择器资源,请将其分配到 ListBox 的 ItemTemplateSelector 属性。 ListBox 为基础集合中的每一项调用 TaskListDataTemplateSelector 的 SelectTemplate 方法。 该调用会将数据对象作为项参数来传递。 然后,将由该方法返回的 DataTemplate 应用于该数据对象。

 

<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}"
ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
HorizontalContentAlignment="Stretch"/>

使用模板选择器后,ListBox 现在如下所示:

这正是此示例要得到的结果。有关完整示例,请参见 Introduction to Data Templating Sample(数据模板化简介示例)

 

 

使用Style切换模板

<DataTemplate x:Key="personTemplate" TargetType="{x:Type local:TaskModel}">
<TextBlock Text="I'm an Open Task" />
</DataTemplate> <DataTemplate x:Key="companyTemplate" TargetType="{x:Type local:TaskModel}">
<TextBlock Text="I'm a Closed Task" />
</DataTemplate> <DataTemplate DataType="{x:Type local:TaskModel}"><ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding AccountType}" Value="Person">
<Setter Property="ContentTemplate" Value="{StaticResource personTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding AccountType}" Value="Company">
<Setter Property="ContentTemplate" Value="{StaticResource companyTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>

 

上面这个例子没有给一个默认的ContentTemplate,我们可以改为:

<DataTemplate x:Key="OpenTaskTemplate" TargetType="{x:Type local:TaskModel}">
<TextBlock Text="I'm an Open Task" />
</DataTemplate> <DataTemplate x:Key="ClosedTaskTemplate" TargetType="{x:Type local:TaskModel}">
<TextBlock Text="I'm a Closed Task" />
</DataTemplate> <DataTemplate DataType="{x:Type local:TaskModel}">
<ContentControl Content="{Binding }">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}"> <!-- Default Template -->
<Setter Property="ContentTemplate" Value="{StaticResource OpenTaskTemplate}" /> <!-- Triggers to change Template -->
<Style.Triggers>
<DataTrigger Binding="{Binding TaskStatus}" Value="Closed">
<Setter Property="ContentTemplate" Value="{StaticResource ClosedTaskTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>

 

使用DataTrigger切换模板

 

<DataTemplate DataType="{x:Type viewModels:CorePlugViewModel}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" Margin="4"></TextBlock>
<ContentControl x:Name="viewBox" Grid.Row="1" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image Source="{Binding MapThumbnail}" />
</ContentControl>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding HasMap}" Value="True">
<Setter Property="Template" TargetName="viewBox">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<views:CorePlugWithMap VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinHeight="10"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

 

如果您的 Setters 相关属性不是当前 DataTemplate 中元素的属性,则使用 Style(用于 ListBoxItem 类)设置属性更合适(如果您要绑定的控件是 ListBox)。

 

比较

方式 注意事项 适用
DataTemplateSelector 无法相应propertyChanged事件 静态更改模板
StyleTriger   能够动态更改绑定模板
DataTriger Setters 相关属性不是当前 DataTemplate 中元素的属性,则使用 Style 能够动态更改绑定模板

 

 

 

参考

Change Data template dynamically

数据模板化概述

[WPF系列]-数据邦定之DataTemplate 根据对象属性切换模板的更多相关文章

  1. [WPF系列]-数据邦定之DataTemplate 对分层数据的支持

    到目前为止,我们仅讨论如何绑定和显示单个集合. 某些时候,您要绑定的集合包含其他集合. HierarchicalDataTemplate 类专用于 HeaderedItemsControl 类型以显示 ...

  2. [WPF系列]-数据邦定之DataTemplate简介

    引言 WPF 数据模板化模型为定义数据的表示形式提供了很大的灵活性.WPF 控件有支持自定义数据表示形式的内置功能.首先介绍下如何定义Datatemplate,然后再介绍其他数据模板化功能,例如根据自 ...

  3. [WPF系列]-数据邦定之DataTemplate 使用 DataTrigger 来应用属性值

    使用 DataTrigger 来应用属性值 当前表示不会告诉我们某个 Task 是家庭任务还是办公室任务.记住 Task 对象拥有类型为 TaskType 的 TaskType 属性,该类型是一个枚举 ...

  4. [WPF系列]-数据邦定之DataTemplate 对 ItemsControl 进行样式和模板处理

    引言   即使 ItemsControl 不是 DataTemplate 所用于的唯一控件类型,将 ItemsControl 绑定到集合仍然很常见. 在 DataTemplate 中有哪些内容一节中, ...

  5. ASP.NET中数据邦定效率问题的一点看法 - 转载(自由的天空)

    在 做Asp.NET开发的时候经常用到DataList.Repeater等,用这些控件的时候经常用到数据邦定,很多程序员都是按照MS提供的方 法<%#DataBinder.Eval(Contai ...

  6. js系列教程2-对象、构造函数、对象属性全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...

  7. fastreport for .net 数据邦定

    C# Code: private void button4_Click(object sender, EventArgs e){   //打印主从表数据    string file = Applic ...

  8. [WPF系列]-ListBox

    引言 本文就WPF中的ListBox常用项给以实例代码演示,包括隐蔽属性的设置,Style设置,以及ControlTemplate的自定义.   Listbox平滑滚动 <ListBox Ite ...

  9. [WPF系列]-TreeView的常用事项

    引言 项目经常会用Treeview来组织一些具有层级结构的数据,本节就将项目使用Treeview常见的问题作一个总结. DataBinding数据绑定 DataTemplate自定义 <Hier ...

随机推荐

  1. MySQL数据迁移到MSSQL-以小米数据库为例-测试828W最快可达到2分11秒

    这里采用.NET Framework 4.0以上版本中新出现的 ConcurrentQueue<T> 类 MSDN是这样描述的: ConcurrentQueue<T> 类是一个 ...

  2. Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室)

    简介       ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端 ...

  3. UDS(ISO14229-2006) 汉译(No.1 范围)

    ISO14229指定的数据链路是独立于诊断服务的,该数据链路允许测试仪(Client)操作ECU(Server)中的诊断功能(如电子燃油喷射.变速箱.ABS等)并接入一条嵌入车辆的串行数据链路.它指定 ...

  4. Linux实战问题解决方案(1):Could not get lock

    环境: Ubuntu12.04 问题描述: Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily un ...

  5. php实现设计模式之 组合模式

    <?php /** * 组合模式 * * 将对象组合成树形结构以表示"部分-整体"的层次结构,使得客户对单个对象和复合对象的使用具有一致性 * * * 1) 抽象构件角色Co ...

  6. Castle Windsor常用介绍以及其在ABP项目的应用介绍

    最近在研究ABP项目,有关ABP的介绍请看阳光铭睿 博客,ABP的DI和AOP框架用的是Castle Windsor下面就对Castle Windsor项目常用方法介绍和关于ABP的使用总结 1.下载 ...

  7. JS时间戳格式化日期时间

    由于mysql数据库里面存储时间存的是时间戳,取出来之后,JS要格式化一下显示.(李昌辉) 用的次数比较多,所以写了一个简单方法来转换: //时间戳转时间 function RiQi(sj) { va ...

  8. [Cordova] 手机网页里的1px

    [Cordova] 手机网页里的1px 1px的显示 Cordova让开发人员可以使用HTML页面,来开发APP的显示内容.但是在手机上,HTML页面里定义的1px,并不是直接对应到手机屏幕的一个像素 ...

  9. 小记max-with与 max-device-width

    max-with是浏览器的宽度,max-device-width是设备显示器的宽度 浏览器宽度不等于显示器宽度 浏览器可以缩小 1.max-device-width是设备整个显示区域的宽度,例如,真实 ...

  10. 使用Object.create 克隆对象以及实现单继承

    var Plane = function () { this.blood = 100; this.attack = 1; this.defense = 1; }; var plane = new Pl ...