将自定义类作为TreeViewItem添加到TreeView WPF

时间:2019-03-04 11:52:46

标签: c# wpf observablecollection datatemplate hierarchicaldatatemplate

我的TreeView如下图所示:

  • MainParent
  • 。>-父母
  • ...>-Child1
  • ...>-Child2
  • ...>-Child3
  • ...>-Child4
  • ...>-Child5
  • ......> Child1_Of_Child5
  • ...........> Child1(Child1_Of_Child5)
  • ...........> Child2(Child1_Of_Child5)
  • ......> Child2_of_Child5
  • ...........> Child1(Child2_Of_Child5)
  • ...........> Child2(Child2_Of_Child5)

我能够使用HierarchicalDataTemplate将ObservableCollection绑定到Child1 / Child2 /../ Child5。 虽然我可以将Child1_Of_Child5添加到Child5 ObservableCollection(在调试模式下看到),但在UI / Treeview中没有反映。

以下是我的XAML代码:

<TreeView.ItemTemplate>
                    <HierarchicalDataTemplate DataType="{x:Type VM:ProjectViewModel}" ItemsSource="{Binding SelectActivityViewModelCollection}">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
                            <TextBlock Text="{Binding Header}"></TextBlock>
                        </StackPanel>
                        <HierarchicalDataTemplate.ItemTemplate>
                            <HierarchicalDataTemplate DataType="{x:Type VM:SelectActivityViewModel}" ItemsSource="{Binding ToolsViewModelCollection}"
                                     >
                                <StackPanel Orientation="Horizontal">
                                    <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
                                    <TextBlock Text="{Binding Header}"></TextBlock>
                                </StackPanel>
                                <HierarchicalDataTemplate.ItemTemplate>
                                    <HierarchicalDataTemplate DataType="{x:Type VM:ToolsViewModel}" ItemsSource="{Binding SheetsViewModelBaseCollection}">
                                        <StackPanel Orientation="Horizontal">
                                            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
                                            <TextBlock Text="{Binding Header}"></TextBlock>
                                        </StackPanel>
                                        <HierarchicalDataTemplate.ItemTemplate>
                                            <HierarchicalDataTemplate x:Name="LastLevel" DataType="{x:Type VM:ViewModelBase}" ItemsSource="{Binding FeaturesViewModelCollection}">
                                                <StackPanel Orientation="Horizontal">
                                                    <Image Source="./resources/file.png" Width="15" Height="15"/>
                                                    <TextBlock Text="{Binding Header}"/>
                                                </StackPanel>
                                            </HierarchicalDataTemplate>
                                        </HierarchicalDataTemplate.ItemTemplate>

                                    </HierarchicalDataTemplate>
                                </HierarchicalDataTemplate.ItemTemplate>
                            </HierarchicalDataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>

类结构: (ViewModelBase扩展到了所有类)

  • ProjectViewModel-具有SelectActivityViewModelCollection =(ObservableCollection(SelectActivityViewModel))
  • SelectActivityViewModel-具有ToolsViewModelCollection =(OC(ToolsViewModel))
  • ToolsViewModel-具有SheetsViewModelBaseCollection和FeaturesViewModelCollection =(OC(ViewModelBase)和OC(FeaturesViewModel))
  • FeaturesViewModel-具有UseCaseViewModelCollection =(OC(UseCaseViewModel))
  • 在ToolsViewModel中,我使用SheetsViewModelBaseCollection来存储Child1 / Child2 /.../ Child5
  • 和FeaturesViewModelCollection-存储Child1_Of_Child5 / Child2_Of_Child5 /../ Child(n)_Of_Child5
  • 编辑:由于我已经将ViewModelBase扩展到所有类,因此我正在使用OC(ViewModelBase)存储不同的图纸(即SheetsViewModelCollection中的图纸)。 注意:

    1. 不使用数据库:使用序列化和反序列化
    2. WPF:遵循MVVM模式

Image shows complete TreeView and OC of respective classes

1 个答案:

答案 0 :(得分:0)

我试图在一个示例项目中重现您的问题。

根据您的描述,ToolsViewModel具有两个集合(SheetsViewModel和FeaturesViewModel的集合)。 如果要在树中显示这两个对象,则必须创建一个包含所有这些对象的单个集合。

我创建了一个名为ViewModelCollection的附加集合,以显示其工作方式。

对于我的测试,我定义了以下类:

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

namespace TreeViewTest
{
  class ViewModelBase
  {
  }

  class ViewModel
  {
    public ObservableCollection<ProjectViewModel>  ProjectViewModelCollection { get; private set; }

    public ViewModel ( )
    {
      ProjectViewModelCollection = new ObservableCollection<ProjectViewModel>() ;
      ProjectViewModelCollection.Add ( new ProjectViewModel() ) ;
      ProjectViewModelCollection.Add ( new ProjectViewModel() ) ;
    }
  }

  class ProjectViewModel
  {
    public ObservableCollection<SelectActivityViewModel>  SelectActivityViewModelCollection { get; private set; }
    public string Header { get ; } = "ProjectViewModel" ;

    public ProjectViewModel ( )
    {
      SelectActivityViewModelCollection = new ObservableCollection<SelectActivityViewModel>() ;
      SelectActivityViewModelCollection.Add ( new SelectActivityViewModel() ) ;
      SelectActivityViewModelCollection.Add ( new SelectActivityViewModel() ) ;
    }

  }

  class SelectActivityViewModel
  {
    public ObservableCollection<ToolsViewModel>  ToolsViewModelCollection  { get; private set; }
    public string Header { get ; } = "SelectActivityViewModel" ;

    public SelectActivityViewModel ( )
    {
      ToolsViewModelCollection = new ObservableCollection<ToolsViewModel>() ;
      ToolsViewModelCollection.Add ( new ToolsViewModel() ) ;
      ToolsViewModelCollection.Add ( new ToolsViewModel() ) ;
    }
  }

  class ToolsViewModel
  {
    public ObservableCollection<SheetsViewModel>    SheetsViewModelCollection    { get; private set; }
    public ObservableCollection<FeaturesViewModel>  FeaturesViewModelCollection  { get; private set; }
    public ObservableCollection<ViewModelBase>      ViewModelCollection          { get; private set; }
    public string Header { get ; } = "ToolsViewModel" ;

    public ToolsViewModel ( )
    {
      SheetsViewModelCollection = new ObservableCollection<SheetsViewModel>() ;
      SheetsViewModelCollection.Add ( new SheetsViewModel() ) ;
      SheetsViewModelCollection.Add ( new SheetsViewModel() ) ;

      FeaturesViewModelCollection = new ObservableCollection<FeaturesViewModel>() ;
      FeaturesViewModelCollection.Add ( new FeaturesViewModel() ) ;
      FeaturesViewModelCollection.Add ( new FeaturesViewModel() ) ;

      // Make a single collection with all children
      ViewModelCollection = new ObservableCollection<ViewModelBase>() ;
      foreach ( var o in SheetsViewModelCollection )
        ViewModelCollection.Add ( o ) ;
      foreach ( var o in FeaturesViewModelCollection )
        ViewModelCollection.Add ( o ) ;
    }
  }

  class SheetsViewModel : ViewModelBase
  {
    public string Header { get ; } = "SheetsViewModel" ;
  }

  class FeaturesViewModel : ViewModelBase
  {
    public ObservableCollection<UseCaseViewModel>  UseCaseViewModelCollection   { get; private set; }
    public string Header { get ; } = "FeaturesViewModel" ;

    public FeaturesViewModel ( )
    {
      UseCaseViewModelCollection = new ObservableCollection<UseCaseViewModel>() ;
      UseCaseViewModelCollection.Add ( new UseCaseViewModel() ) ;
      UseCaseViewModelCollection.Add ( new UseCaseViewModel() ) ;
    }
  }

  class UseCaseViewModel
  {
    public string Header { get ; } = "UseCaseViewModel" ;
  }
}

我对XAML进行了一些更改:

(1)我为以下内容定义了其他模板:

  • FeaturesViewMode
  • SheetsViewModel
  • UseCaseViewModel

(2)我已经将HierarchicalDataTemplate定义为没有任何嵌套的资源。

这是个人喜好。我认为您使用HierarchicalDataTemplate.ItemTemplate的方法也可以。

<Window x:Class="TreeViewTest.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:VM="clr-namespace:TreeViewTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
  <Grid>

    <TreeView ItemsSource="{Binding ProjectViewModelCollection}">

      <TreeView.Resources>

        <HierarchicalDataTemplate DataType="{x:Type VM:ProjectViewModel}" ItemsSource="{Binding SelectActivityViewModelCollection}">
          <StackPanel Orientation="Horizontal">
            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
            <TextBlock Text="{Binding Header}"></TextBlock>
          </StackPanel>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type VM:SelectActivityViewModel}" ItemsSource="{Binding ToolsViewModelCollection}">
          <StackPanel Orientation="Horizontal">
            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
            <TextBlock Text="{Binding Header}"></TextBlock>
          </StackPanel>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type VM:ToolsViewModel}" ItemsSource="{Binding ViewModelCollection}">
          <StackPanel Orientation="Horizontal">
            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
            <TextBlock Text="{Binding Header}"></TextBlock>
          </StackPanel>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type VM:FeaturesViewModel }" ItemsSource="{Binding UseCaseViewModelCollection}">
          <StackPanel Orientation="Horizontal">
            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
            <TextBlock Text="{Binding Header}"></TextBlock>
          </StackPanel>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type VM:SheetsViewModel}">
          <StackPanel Orientation="Horizontal">
            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
            <TextBlock Text="{Binding Header}"></TextBlock>
          </StackPanel>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type VM:UseCaseViewModel}">
          <StackPanel Orientation="Horizontal">
            <Image Source="./resources/New_Package.png" Width="15" Height="15"/>
            <TextBlock Text="{Binding Header}"></TextBlock>
          </StackPanel>
        </HierarchicalDataTemplate>

      </TreeView.Resources>
    </TreeView>

  </Grid>
</Window>

DataContext在后面的代码中初始化如下。还有其他方法可以做到这一点。

public MainWindow ( )
{
  DataContext = new ViewModel() ;
  InitializeComponent ();
}

我能够在五个级别上显示所有六种类型,如下所示:

Screen shot