Categories: WPF 教程

WPF教程之 TreeViews 数据绑定和多种模板

TreeView控件:

TreeViews 数据绑定和多种模板

WPF TreeView 支持数据绑定(Data Binding),就像其他所有WPF控件一样,但是TreeView却能够天然的支持继承绑定。普通的DataTemplate通常不够高效。因此,我们使用继承数据模板(HierarchicalDataTemplate),它允许我们同时控制节点,以及该节点的子节点。

TreeView 基本数据绑定

在后面的例子中,我将演示使用分层数据模板(HierarchicalDataTemplate)是一件多么简单的工作。

<Window x:Class="WpfTutorialSamples.TreeView_control.TreeViewDataBindingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:self="clr-namespace:WpfTutorialSamples.TreeView_control"
        Title="TreeViewDataBindingSample" Height="150" Width="200">
    <Grid Margin="10">
  <TreeView Name="trvMenu">
   <TreeView.ItemTemplate>
    <HierarchicalDataTemplate DataType="{x:Type self:MenuItem}" ItemsSource="{Binding Items}">
     <TextBlock Text="{Binding Title}" />
    </HierarchicalDataTemplate>
   </TreeView.ItemTemplate>
  </TreeView>
 </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.IO;
using System.Collections.ObjectModel;

namespace WpfTutorialSamples.TreeView_control
{
 public partial class TreeViewDataBindingSample : Window
 {
  public TreeViewDataBindingSample()
  {
   InitializeComponent();
   MenuItem root = new MenuItem() { Title = "Menu" };
   MenuItem childItem1 = new MenuItem() { Title = "Child item #1" };
   childItem1.Items.Add(new MenuItem() { Title = "Child item #1.1" });
   childItem1.Items.Add(new MenuItem() { Title = "Child item #1.2" });
   root.Items.Add(childItem1);
   root.Items.Add(new MenuItem() { Title = "Child item #2" });
   trvMenu.Items.Add(root);
  }
 }

 public class MenuItem
 {
  public MenuItem()
  {
   this.Items = new ObservableCollection<MenuItem>();
  }

  public string Title { get; set; }

  public ObservableCollection<MenuItem> Items { get; set; }
 }

}

在XAML结构化文件中,可以看到TreeView的ItemTemplate具有一个HierarchicalDataTemplate。通过设置这个模板的ItemsSource属性,我指示它使用Items属性来查找子元素,并且我在内部定义了一个真正的模板,该模板只包含一个绑定到Title属性的TextBlock。

第一个例子非常简单,以至于我们只是手动添加了TreeView的元素,而不是生成一组对象并且绑定他们。但是,随着操作越来越复杂,使用数据绑定的优势会更加明显。

多个模板对于不同类型数据

下面这个例子,将增加一点复杂度,我想显示出一个家族树以及成员。一个家族使用一种方式来表现,而成员使用另一种方式来表现。为了完成以一点,我将创建两个模板,并且将他们作为资源指定给这棵树(或者这个窗口,或者这个程序,全都看你),然后令TreeView根据数据的类型选择正确的模板

以下是实现代码 – 随后将进行解释:

<Window x:Class="WpfTutorialSamples.TreeView_control.TreeViewMultipleTemplatesSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:self="clr-namespace:WpfTutorialSamples.TreeView_control"
        Title="TreeViewMultipleTemplatesSample" Height="200" Width="250">
 <Grid Margin="10">
  <TreeView Name="trvFamilies">
   <TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type self:Family}" ItemsSource="{Binding Members}">
     <StackPanel Orientation="Horizontal">
      <Image Source="/WpfTutorialSamples;component/Images/group.png" Margin="0,0,5,0" />
      <TextBlock Text="{Binding Name}" />
      <TextBlock Text=" [" Foreground="Blue" />
      <TextBlock Text="{Binding Members.Count}" Foreground="Blue" />
      <TextBlock Text="]" Foreground="Blue" />
     </StackPanel>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type self:FamilyMember}">
     <StackPanel Orientation="Horizontal">
      <Image Source="/WpfTutorialSamples;component/Images/user.png" Margin="0,0,5,0" />
      <TextBlock Text="{Binding Name}" />
      <TextBlock Text=" (" Foreground="Green" />
      <TextBlock Text="{Binding Age}" Foreground="Green" />
      <TextBlock Text=" years)" Foreground="Green" />
     </StackPanel>
    </DataTemplate>
   </TreeView.Resources>
  </TreeView>
 </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Collections.ObjectModel;

namespace WpfTutorialSamples.TreeView_control
{
 public partial class TreeViewMultipleTemplatesSample : Window
 {
  public TreeViewMultipleTemplatesSample()
  {
   InitializeComponent();

   List<Family> families = new List<Family>();

   Family family1 = new Family() { Name = "The Does" };
   family1.Members.Add(new FamilyMember() { Name = "John Doe", Age = 42 });
   family1.Members.Add(new FamilyMember() { Name = "Jane Doe", Age = 39 });
   family1.Members.Add(new FamilyMember() { Name = "Sammy Doe", Age = 13 });
   families.Add(family1);

   Family family2 = new Family() { Name = "The Moes" };
   family2.Members.Add(new FamilyMember() { Name = "Mark Moe", Age = 31 });
   family2.Members.Add(new FamilyMember() { Name = "Norma Moe", Age = 28 });
   families.Add(family2);

   trvFamilies.ItemsSource = families;
  }
 }

 public class Family
 {
  public Family()
  {
   this.Members = new ObservableCollection<FamilyMember>();
  }

  public string Name { get; set; }

  public ObservableCollection<FamilyMember> Members { get; set; }
 }

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

  public int Age { get; set; }
 }
}

就像前面说到的,这两个模板被定义为TreeView的资源的一部分,并且允许TreeView根据不同的数据类型选择合适的模板进行展示。展示Family类型的模板被定义为分层模板(hierarchical template),并且使用Members属性显示家庭成员。

FamilyMember数据类型所使用的模板被定义为常规的数据模板(DataTemplate),因为这个类型没有任何子成员。但是,如果我们希望所有FamilyMember都有子成员,并且这些子成员还有子成员,那么就应该使用分层模板(hierarchical template)

在这两种模板中,我们都是用了一个图片表示了该节点是一个家庭还是家庭成员,并且展示了一些感兴趣的数据,比如家庭成员的数量,或者成员的年龄。

在后台代码中,我们只是简单的创建了两个Family的实例,并且使用一组家庭成员填充他们,然后将这些Family加入到一个列表,也就是TreeView的数据源。

小结

使用数据绑定,可以非常个性化TreeView,也可以使用多个模板表示不同的数据,表现可能性是无尽的。

admin

这个人很懒,什么都没有留下~

Share
Published by
admin

Recent Posts

在 Chrome 中删除、允许和管理 Cookie

您可以选择删除现有 Cooki…

21 小时 ago

自定义指令:聊聊vue中的自定义指令应用法则

今天我们来聊聊vue中的自定义…

1 周 ago

聊聊Vue中@click.stop和@click.prevent

一起来学下聊聊Vue中@cli…

2 周 ago

Nginx 基本操作:启动、停止、重启命令。

我们来学习Nginx基础操作:…

3 周 ago

Vue3:手动清理keep-alive组件缓存的方法

Vue3中手动清理keep-a…

3 周 ago

聊聊React和Vue组件更新的实现及区别

React 和 Vue 都是当…

4 周 ago