引言

书接上回[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. React Native文件介绍

    一.index.ios.js文件中的东西 index.ios.js文件,是js代码的入口文件,所有的代码编写从这开始,可以定义自己的模块和引入第三方模块. import React, { Compon ...

  2. C# 将DataTable数据源转换成实体类

    using System; using System.Collections.Generic; using System.Data; using System.Reflection; /// < ...

  3. 模仿迅L看看<音频播放器> 实现点击进度条,跳转播放

    <Style x:Key="btnFallback" TargetType="{x:Type Button}"> <Setter Proper ...

  4. .net源码分析 – List<T>

    通过分析源码可以更好理解List<T>的工作方式,帮助我们写出更稳定的代码. List<T>源码地址: https://github.com/dotnet/corefx/blo ...

  5. cron表达式详解[转]

    Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth Month ...

  6. SQL Server帐号孤立的问题解决

    网站近日经常遭到攻击,好几次数据库挂马,前几天把论坛升级了,今天又升级了数据库,把之前的MSSQL 2000 升级到MSSQL 2005,用的是数据库还原功能还原的,遇到了这个帐号孤立的问题. 什么是 ...

  7. CSS:CSS使用Tips

    Css是前端开发中效果展现的主要部分之一,良好的Css书写习惯可以为实际的项目开发提高效率,也可以为实现良好的团队合作提供保证. 一般新手在使用Css的时候经常会犯一些错误,出现一些不经意的漏洞,如果 ...

  8. 基于highcharts封装的组件-demo&源码

    前段时间做的项目中需要用到highcharts绘制各种图表,其实绘制图表本身代码很简单,但是由于需求很多,有大量的图形需要绘制,所以就不得不复制粘贴大量重复(默认配置等等)的代码,所以,后来抽空自己基 ...

  9. 【翻译】理念:无冲突的扩展本地DOM原型

    菜鸟翻译,望大家多多指正哈 原文:http://lea.verou.me/2015/04/idea-extending-native-dom-prototypes-without-collisions ...

  10. browserify学习总结

    前言 在未接触browserify,虽然我知道它是一个前端构建工具,但还是有几个疑问: 1. browserify出现的日期? 2. 能构建哪些文件? 3. 附加的browserify代码体积是多大? ...