C# 将自定义类作为TreeView项目添加到TreeView WPF

C# 将自定义类作为TreeView项目添加到TreeView WPF,c#,wpf,observablecollection,datatemplate,hierarchicaldatatemplate,C#,Wpf,Observablecollection,Datatemplate,Hierarchicaldatatemplate,我的树状视图如下所示: 主要父母 .>-家长 …孩子1 …孩子2 …孩子3 …孩子4 …孩子5 ……孩子们一个孩子一个孩子五个孩子 儿童1(儿童1/5) 儿童2(儿童1/5) ……孩子2个孩子中的孩子5个 儿童1(儿童2/5) 儿童2(儿童2/5) 我能够使用HierarchycalDataTemplate将ObservableCollection绑定到Child1/Child2//Child5。 虽然我能够将Child1\u Of_Child5添加到Child5 observetecoll

我的树状视图如下所示:

  • 主要父母
  • .>-家长
  • …孩子1
  • …孩子2
  • …孩子3
  • …孩子4
  • …孩子5
  • ……孩子们一个孩子一个孩子五个孩子
  • 儿童1(儿童1/5)
  • 儿童2(儿童1/5)
  • ……孩子2个孩子中的孩子5个
  • 儿童1(儿童2/5)
  • 儿童2(儿童2/5)
我能够使用HierarchycalDataTemplate将ObservableCollection绑定到Child1/Child2//Child5。 虽然我能够将Child1\u Of_Child5添加到Child5 observetecollection(在调试模式下看到),但在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-has ToolsViewModelCollection=(OC(ToolsViewModel))
  • ToolsViewModel-具有SheetsViewModelBaseCollection和FeaturesViewModelCollection=(OC(ViewModelBase)和OC(FeaturesViewModel))
  • FeaturesViewModel-具有UseCaseViewModelCollection=(OC(UseCaseViewModel))
  • 在ToolsViewModel中,我使用SheetsViewModelBaseCollection存储Child1/Child2/../Child5
  • 和功能查看模型集合-存储Child1\u Of Child5/Child2\u Of Child5//Child(n)\u Of Child5
  • 编辑:由于我已将ViewModelBase扩展到所有类,因此我使用OC(ViewModelBase)存储不同的图纸(.即,在SheetsViewModelCollection中)。 注:

  • 未使用数据库:使用序列化和反序列化
  • WPF:遵循MVVM模式

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

根据您的描述,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" ;
  }
}
我能够在五个级别上显示所有六种类型,如下所示:


谢谢您的回复,Dymanoid!我很抱歉,我在描述上犯了一个错误。SheetsViewModelCollection是OC(ViewModelBase)。由于我已将ViewModelBase扩展到所有类,因此我使用OC(ViewModelBase)存储不同的图纸。为了一般地指定一个类类型,我在XAML中使用ViewModelBase。我不确定这是否重要,但Dymanoid是错误的。Datatemplates将与基类一起工作。我想他已经把风格和目标型搞混了。谢谢你的回复,乔兰斯先生。正如您所示,仅应为ToolsViewModel的最后一个SheetsViewModel创建FeaturesViewModel。为了清楚起见,My Each FeaturesViewModel将创建一个TabItem,OC将在其中映射到DataGrid。即,My Each UseCaseViewModel将用于存储行信息。在您尝试过的示例中,如果我们可以创建featureViewModel并将CaseViewModel用作其子级,则树结构。将完成。请参考qsn中的图像。这有两个问题:(1)ToolsViewModel的模板将ItemsSource指定为SheetsViewModelCollection而不是FeaturesViewModelCollection,因此FeaturesViewModel不会出现在树中。您必须选择一个或另一个,或者您必须创建一个包含这两者的子级集合(2)FeaturesViewModel没有模板,UseCaseViewModel没有模板。我可以稍后更新我的示例。我或多或少地重写了我的答案。
<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>
public MainWindow ( )
{
  DataContext = new ViewModel() ;
  InitializeComponent ();
}