WPF中如何根据数据类型使用不同的数据模板

我们在将一个数据集合绑定到列表控件时,有时候想根据不同的数据类型,显示为不同的效果。

例如将一个文件夹集合绑定到ListBox时,系统文件夹和普通文件夹分别显示为不同的效果,就可以使用模板选择器功能。

WPF提供了一个模板选择器类型DataTemplateSelector ,它可以根据数据对象和数据绑定元素来选择 DataTemplate

使用方法

创建一个类,继承自DataTemplateSelector,并重写SelectTemplate方法。

类似下面这样

复制代码
 1 using System.Windows;
 2 using System.Windows.Controls;
 3 
 4 namespace SDKSample
 5 {
 6     public class TaskListDataTemplateSelector : DataTemplateSelector
 7     {
 8         public override DataTemplate
 9             SelectTemplate(object item, DependencyObject container)
10         {
11             FrameworkElement element = container as FrameworkElement;
12 
13             if (element != null && item != null && item is Task)
14             {
15                 Task taskitem = item as Task;
16 
17                 if (taskitem.Priority == 1)
18                     return
19                         element.FindResource("importantTaskTemplate") as DataTemplate;
20                 else
21                     return
22                         element.FindResource("myTaskTemplate") as DataTemplate;
23             }
24 
25             return null;
26         }
27     }
28 }

下面我们使用ListBoxTreeView进行演示

ListBox的使用示例

我们先定义如下的数据模型

复制代码
 1  public class FileData
 2  {
 3      public string FileName { get; set; }
 4  }
 5 
 6  public class FileData1 : FileData
 7  {
 8      public string FileData1Property { get; set; }
 9  }
10 
11  public class FileData2:FileData
12  {
13      public string FileData2Property { get; set; }
14  }

然后定义一个资源字典,分别在里面定义两种数据的数据模板

复制代码
 1 <DataTemplate x:Key="FileData1Datatemplate">
 2     <Grid>
 3         <Grid.ColumnDefinitions>
 4             <ColumnDefinition/>
 5             <ColumnDefinition/>
 6         </Grid.ColumnDefinitions>
 7         <Label Content="{Binding FileName}" FontSize="20" Foreground="Green"></Label>
 8         <Label Content="{Binding FileData1Property}" Grid.Column="1" VerticalAlignment="Center"></Label>
 9     </Grid>
10 </DataTemplate>
11 
12 <DataTemplate x:Key="FileData2Datatemplate">
13     <Grid>
14         <Grid.ColumnDefinitions>
15             <ColumnDefinition/>
16             <ColumnDefinition/>
17         </Grid.ColumnDefinitions>
18         <Label Content="{Binding FileName}" FontSize="16" Foreground="Red"></Label>
19         <Label Content="{Binding FileData2Property}" Grid.Column="1" VerticalAlignment="Center"></Label>
20     </Grid>
21 </DataTemplate>

添加测试数据

复制代码
 1  List<FileData> fileDatas = new List<FileData>();
 2  FileData1 fileData1 = new FileData1();
 3  fileData1.FileName = "1.jpg";
 4  fileData1.FileData1Property = "1.jpg property";
 5  FileData2 fileData2 = new FileData2();
 6  fileData2.FileName = "2.jpg";
 7  fileData2.FileData2Property = "2.jpg property";
 8  fileDatas.Add(fileData1);
 9  fileDatas.Add(fileData2);
10  this.listbox.ItemsSource = fileDatas;

然后再为ListBox 设置DataTemplateSelector

复制代码
1  this.listbox.ItemTemplateSelector = new ItemDataTemplateSelector();

运行效果如下:

TreeView的使用示例

这里我们定义一个磁盘和文件夹的数据类型,一个磁盘对象可以包含多个文件夹

复制代码
 1  public class Disk
 2  {
 3      public string DiskName { get; set; }
 4 
 5      public List<Folder> Folders { get; set; } = new List<Folder>();
 6  }
 7 
 8  public class Folder
 9  {
10      public string FullPath { get; set; }
11 
12      public long Size { get; set; }
13  }

使用使用HierarchicalDataTemplateTreeView设置层级的数据模板

针对DiskHierarchicalDataTemplate

复制代码
 1 <HierarchicalDataTemplate x:Key="DiskDatatemplate" ItemsSource="{Binding Folders}" DataType="{x:Type local:Disk}">
 2     <Grid>
 3         <Grid.ColumnDefinitions>
 4             <ColumnDefinition Width="25"/>
 5             <ColumnDefinition/>
 6         </Grid.ColumnDefinitions>
 7 
 8         <Image Source="disk.png" Height="25"></Image>
 9         <Label Content="{Binding DiskName}" Grid.Column="1"></Label>
10     </Grid>
11 </HierarchicalDataTemplate>

针对FolderHierarchicalDataTemplate

复制代码
 1  <HierarchicalDataTemplate x:Key="FolderDatatemplate" DataType="{x:Type local:Folder}">
 2      <Grid>
 3          <Grid.ColumnDefinitions>
 4              <ColumnDefinition Width="25"/>
 5              <ColumnDefinition Width="auto"/>
 6              <ColumnDefinition/>
 7          </Grid.ColumnDefinitions>
 8 
 9          <Image Source="folder.png" Height="25"></Image>
10          <Label Content="{Binding FullPath}" Grid.Column="1"></Label>
11          <Label Content="{Binding Size}" Grid.Column="2"></Label>
12      </Grid>
13  </HierarchicalDataTemplate>

然后我们创建一个DataTemplateSelector ,根据不同的数据类型返回不同的HierarchicalDataTemplate

这里仅做演示,实际使用时推荐使用switch并增加错误检测。

复制代码
 1  public class NodeDataTemplateSelector : DataTemplateSelector
 2  {
 3      public override DataTemplate SelectTemplate(object item, DependencyObject container)
 4      {
 5          if (item is Disk)
 6              return Application.Current.FindResource("DiskDatatemplate") as DataTemplate;
 7          else
 8              return Application.Current.FindResource("FolderDatatemplate") as DataTemplate;
 9      }
10  }

添加测试数据

复制代码
 1 Disk disk = new Disk();
 2 disk.DiskName = "D:\\";
 3 
 4 Folder folder = new Folder();
 5 folder.FullPath = "D:\\Software";
 6 folder.Size = 1024;
 7 disk.Folders.Add(folder);
 8 
 9 Disk disk2 = new Disk();
10 disk2.DiskName = "E:\\";
11 
12 Folder folder2 = new Folder();
13 folder2.FullPath = "E:\\Documents";
14 folder2.Size = 2048;
15 disk2.Folders.Add(folder2);
16 
17 List<Disk> disks = new List<Disk>();
18 disks.Add(disk);
19 disks.Add(disk2);
20 
21 this.treeview.ItemsSource = disks;

TreeView 设置DataTemplateSelector

复制代码
1   this.treeview.ItemTemplateSelector = new NodeDataTemplateSelector();

运行效果

示例代码

github

参考资料:

DataTemplateSelector 类 (System.Windows.Controls) | Microsoft Learn

相关推荐
明耀12 小时前
WPF TabControl 设置item不能点击
wpf
军训猫猫头14 小时前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
明耀14 小时前
WPF 设置平均布局 如果隐藏的话,能够自动扩展
wpf
晚安苏州1 天前
WPF DataTemplate 数据模板
wpf
甜甜不吃芥末2 天前
WPF依赖属性详解
wpf
Hat_man_2 天前
WPF制作图片闪烁的自定义控件
wpf
晚安苏州3 天前
WPF Binding 绑定
wpf·wpf binding·wpf 绑定
wangnaisheng3 天前
【WPF】RenderTargetBitmap的使用
wpf
dotent·4 天前
WPF 完美解决改变指示灯的颜色
wpf
orangapple6 天前
WPF 用Vlc.DotNet.Wpf实现视频播放、停止、暂停功能
wpf·音视频