将自定义类作为TreeViewItem添加到TreeView WPF [英] Adding Custom Class as TreeViewItem to TreeView WPF
问题描述
我的TreeView如下图所示:
I have scenario where my TreeView look like below:
- 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)
- MainParent
- .>-Parent
- ...>--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中没有反映同样的内容.
I am able to bind ObservableCollection till Child1/Child2/../Child5 using HierarchicalDataTemplate. Though I am able to add Child1_Of_Child5 to Child5 ObservableCollection (seen in debug mode), Same is not reflecting in UI/Treeview.
以下是我的XAML代码:
Below is my XAML code:
<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扩展到了所有类)
Class Structure: (ViewModelBase is extended to all classes)
- 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中的图纸). 注意:
- ProjectViewModel - has SelectActivityViewModelCollection = (ObservableCollection(SelectActivityViewModel))
- SelectActivityViewModel - has ToolsViewModelCollection = (OC(ToolsViewModel))
- ToolsViewModel - has SheetsViewModelBaseCollection and FeaturesViewModelCollection = (OC(ViewModelBase) and OC(FeaturesViewModel))
- FeaturesViewModel - has UseCaseViewModelCollection = (OC(UseCaseViewModel))
- In ToolsViewModel I am using SheetsViewModelBaseCollection to store Child1/Child2/.../Child5
- and FeaturesViewModelCollection - to store Child1_Of_Child5/Child2_Of_Child5/../Child(n)_Of_Child5
EDIT : As i have extended ViewModelBase to all classes, i am using OC(ViewModelBase) to store different sheets(.i.e.,in SheetsViewModelCollection). Note:
- 不使用数据库:使用序列化和反序列化
- WPF:遵循MVVM模式
推荐答案
我试图在示例项目中重现您的问题.
I have tried to reproduce your problem in a sample project.
根据您的描述,ToolsViewModel具有两个集合(SheetsViewModel和FeaturesViewModel的集合). 如果要在树中显示这两个对象,则必须创建一个包含所有这些对象的单个集合.
According to your description, ToolsViewModel has two collections (of SheetsViewModel and of FeaturesViewModel). If you want to show both of these in the tree, you will have to make a single collection containing all of these objects.
我创建了一个名为ViewModelCollection的附加集合,以显示其工作方式.
I have created an additional collection called ViewModelCollection to show how this might work.
对于我的测试,我定义了以下类:
For my tests, I have defined classes as follows:
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进行了一些更改:
I have made some changes to the XAML:
(1)我为以下内容定义了其他模板:
(1) I have defined additional templates for:
- FeaturesViewMode
- SheetsViewModel
- UseCaseViewModel
(2)我已经将HierarchicalDataTemplate定义为没有任何嵌套的资源.
(2) I have defined the HierarchicalDataTemplate as resources without any kind of nesting.
这是个人喜好.我认为您使用HierarchicalDataTemplate.ItemTemplate的方法也可以.
This is personal preference. I think that your approach with HierarchicalDataTemplate.ItemTemplate also works.
<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在后面的代码中初始化如下.还有其他方法可以做到这一点.
The DataContext is initialised in code behind as follows. There are other ways to do this.
public MainWindow ( )
{
DataContext = new ViewModel() ;
InitializeComponent ();
}
我能够在五个级别上显示所有六种类型,如下所示:
I was able to show all six types on five levels as shown below:
这篇关于将自定义类作为TreeViewItem添加到TreeView WPF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!