WPF---数据模版

发布于:2025-08-19 ⋅ 阅读:(19) ⋅ 点赞:(0)

教程:微软文档

1.定义

数据模版就是数据的外衣,这个外衣的颜色,展示的内容和形式,可以由用户自定义。即数据的表象形式。

2.常用知识

2.1 数据模版的定义

  • 指明Key的定义
<DataTemplate x:Key="taskDataTemplate">
    <StackPanel Margin="5" Orientation="Horizontal">
        <CheckBox Margin="5,0,10,0" IsChecked="{Binding IsDone}" />
        <TextBlock VerticalAlignment="Center" FontSize="16" Text="{Binding Name}" />
    </StackPanel>
</DataTemplate>
  • 指明类的定义
<DataTemplate DataType="{x:Type local:Task}">
    <StackPanel Margin="5" Orientation="Horizontal">
        <CheckBox Margin="5,0,10,0" IsChecked="{Binding IsDone}" />
        <Border x:Name="border" BorderBrush="Yellow" BorderThickness="3">
            <TextBlock VerticalAlignment="Center" FontSize="16" Text="{Binding Description}" />
        </Border>
    </StackPanel>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding TaskType}">
            <DataTrigger.Value>
                <local:TaskType>home</local:TaskType>
            </DataTrigger.Value>
            <Setter TargetName="border" Property="Background" Value="LightGreen" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

注意: 此 DataTemplate 会自动应用于所有 Task 对象。 请注意,在这种情况下,x:Key 是隐式设置的。 因此,如果为此 DataTemplate 分配 x:Key 值,你将替代隐式 x:Key,并且不会自动应用 DataTemplate。

2.2 数据模版的DataTrigger

同上

2.3 为数据选择数据模版

  1. 写一类继承自 DataTemplateSelector 并重写方法 SelectTemplate
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("taskDataTemplate") as DataTemplate;
        }

        return null;
    }
}
  1. 在资源里面引用这个数据模版选择器
 <local:TaskListDataTemplateSelector x:Key="taskSelector"/>
  1. 在使用数据模版的控件里面使用属性:ItemTemplateSelector
        <ListBox ItemsSource="{Binding Source={StaticResource myTodoList}}" ItemTemplateSelector="{StaticResource taskSelector}" />

符完整实例

<Window
    x:Class="Study04_数据模版.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:Study04_数据模版"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <Window.Resources>
        <local:Tasks x:Key="myTodoList" />
        <DataTemplate x:Key="taskDataTemplate">
            <StackPanel Margin="5" Orientation="Horizontal">
                <CheckBox Margin="5,0,10,0" IsChecked="{Binding IsDone}" />
                <TextBlock VerticalAlignment="Center" FontSize="16" Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="importantTaskTemplate">
            <StackPanel Margin="5" Orientation="Vertical">
                <CheckBox Margin="5,0,10,0" IsChecked="{Binding IsDone}" />
                <Border BorderBrush="Red" BorderThickness="2" >
                    <TextBlock VerticalAlignment="Center" FontSize="16" Text="{Binding Name}" />
                </Border>
                <TextBlock VerticalAlignment="Center" FontSize="16" Text="{Binding Description}" />
            </StackPanel>
        </DataTemplate>

        <DataTemplate DataType="{x:Type local:Task}">
            <StackPanel Margin="5" Orientation="Horizontal">
                <CheckBox Margin="5,0,10,0" IsChecked="{Binding IsDone}" />
                <Border x:Name="border" BorderBrush="Yellow" BorderThickness="3">
                    <TextBlock VerticalAlignment="Center" FontSize="16" Text="{Binding Description}" />
                </Border>
            </StackPanel>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding TaskType}">
                    <DataTrigger.Value>
                        <local:TaskType>home</local:TaskType>
                    </DataTrigger.Value>
                    <Setter TargetName="border" Property="Background" Value="LightGreen" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>

        <local:TaskListDataTemplateSelector x:Key="taskSelector"/>
    </Window.Resources>
    <Grid>
        <!--<ListBox Margin="10,10,10,10" ItemTemplate="{Binding Source={StaticResource taskDataTemplate}}" ItemsSource="{Binding Source={StaticResource myTodoList}}" />-->

        <!--<ListBox Margin="10,10,10,10" HorizontalContentAlignment="Stretch" ItemsSource="{Binding Source={StaticResource myTodoList}}" />-->

        <ListBox ItemsSource="{Binding Source={StaticResource myTodoList}}" ItemTemplateSelector="{StaticResource taskSelector}" />
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace Study04_数据模版
{
    public class Tasks : ObservableCollection<Task>
    {
        public Tasks()
        {
            Add(new Task { Name = "Task 1", Description = "Description for Task 1", Priority = 1, TaskType = TaskType.work });
            Add(new Task { Name = "Task 2", Description = "Description for Task 2", Priority = 2, TaskType = TaskType.home });
            Add(new Task { Name = "Task 3", Description = "Description for Task 3", Priority = 3, TaskType = TaskType.work });
        }
    }

    public class Task
    {
        public string Name { get; set; }

        public string Description { get; set; }

        public int Priority { get; set; }

        public TaskType TaskType { get; set; }

        public override string ToString()
        {
            return Description.ToString();
        }
    }

    public enum TaskType
    {
        home,
        work,
    }

    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("taskDataTemplate") as DataTemplate;
            }

            return null;
        }
    }
}

3 其它示例

3.1 示例一

  1. 定义数据模版
<DataTemplate x:Key="ControlATemplate">
    <local:RecipeInfoUC DataContext="{Binding DataContext.Parameter, RelativeSource={RelativeSource AncestorType=ContentControl}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>

<!--  控件B的模板 - 当IsRework为True时使用  -->
<DataTemplate x:Key="ControlBTemplate">
    <local:RecipeReworkUC DataContext="{Binding DataContext.Parameter, RelativeSource={RelativeSource AncestorType=ContentControl}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>

  1. 定义数据模版选择器
 /// <summary>
 /// 模板选择器 - 根据IsRework的值选择对应的模板
 /// </summary>
 public class ReworkTemplateSelector : DataTemplateSelector
 {
     /// <summary>
     /// 控件A的模板属性
     /// </summary>
     public DataTemplate ControlATemplate { get; set; }

     /// <summary>
     /// 控件B的模板属性
     /// </summary>
     public DataTemplate ControlBTemplate { get; set; }

     /// <summary>
     /// 模版选择方法
     /// </summary>
     /// <param name="item"></param>
     /// <param name="container"></param>
     /// <returns>模版</returns>
     public override DataTemplate SelectTemplate(object item, DependencyObject container)
     {
         // 检查item是否为bool类型
         if (item is bool isRework)
         {
             // 根据IsRework的值返回对应的模板
             return isRework ? ControlBTemplate : ControlATemplate;
         }

         // 默认返回控件B的模板
         return ControlBTemplate;
     }
 }
  1. 在资源中引用数据模版
<local:ReworkTemplateSelector x:Key="ReworkTemplateSelector" ControlATemplate="{StaticResource ControlATemplate}" ControlBTemplate="{StaticResource ControlBTemplate}" />
  1. 使用数据模版选择器
 <ContentControl Content="{Binding HasReWorkCamera}" ContentTemplateSelector="{StaticResource ReworkTemplateSelector}" />

网站公告

今日签到

点亮在社区的每一天
去签到