具有多个级别的TreeView WPF

时间:2018-12-21 13:24:18

标签: c# .net wpf xaml

我有以下课程:

class Component
{
    ComponentType ComponentType {get; set;}
    string Name {set; set;}
    List<Component> SubComponents {get; set;}
}

enum ComponentType
{
    Feature,
    Role
}

在我的VM上,一个List<Component> AllComponents {get;}包含我所有组件的所有,而与ComponentType无关。

我希望不必Component分隔ComponentType,而是将它们显示在TreeView中,如下所示:

Roles
    ComponentA
    ComponentB
        ComponentC
        ComponentD
    ComponentE
Features
    ComponentF
    ComponentG
        ComponentH
    ComponentI

但是我真的不确定如何在WPF中执行此操作而不必创建两个单独的List<Component>Dictionary<ComponentType, Component>(我也想避免)。

一个非常简单的问题,有没有办法仅使用XAML来实现这一目标?

PS:所有SubComponents都将始终与其父母拥有相同的ComponentType

3 个答案:

答案 0 :(得分:0)

AllComponens应该包含两个分层的Component对象-名称“ Roles”和“ Features”-代表每棵树的根。

然后,“ Roles”对象的SubComponents属性应包含其他三个Component对象(ComponentA,B和E),而“ Features”对象的SubComponents属性还应包含三个子对象对象(F,G和I),例如:

public List<Component> AllComponents { get; } = new List<Component>()
{
    new Component(){ Name = "Roles", SubComponents = new List<Component>(){ new Component() { Name = "A" }, new Component() { Name = "B" }, new Component() { Name = "E" } } },
    new Component(){ Name = "Features",SubComponents = new List<Component>(){ new Component() { Name = "F" }, new Component() { Name = "G" }, new Component() { Name = "I" } } }
};

如果在视图模型中像这样组织数据,则可以使用以下TreeView表示层次结构:

<TreeView ItemsSource="{Binding AllComponents}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding SubComponents}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

答案 1 :(得分:0)

您可以使用CollectionViewSourceDetails),它支持按给定Property的Collection-Item进行分组。

以下是XAML中的一个示例:

<Grid>
    <!-- Define CollectionViewSource (must be declared as static resource) -->
    <Grid.Resources>
        <!-- Bind to Components List and add key 'ComponentTypeGrouper' -->
        <CollectionViewSource x:Key="ComponentTypeGrouper" Source="{Binding AllComponents}">
            <!-- Group by the Property 'ComponentType' -->
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="ComponentType" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Grid.Resources>

    <!-- Set source of TreeView to the 'ComponentGrouper' -->
    <TreeView ItemsSource="{Binding Source={StaticResource ComponentTypeGrouper}}">
        <!-- Hierarchical Template to support nested Components -->
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding SubComponents}">
                <TextBlock Text="{Binding Name}"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
        <!-- Group Container Style (how Roles/Features are displayed) -->
        <TreeView.GroupStyle>
            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <!-- Name of the Groups (expandable as treeviewitem) -->
                                    <TreeViewItem Header="{Binding Name}">
                                        <ItemsPresenter/>
                                    </TreeViewItem>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </TreeView.GroupStyle>
    </TreeView>
</Grid>

答案 2 :(得分:0)

我已经使用TreeviewItemModel做到了这一点:

public class TreeViewItemViewModel : BindableBase
    {

        private string _name;
        private TreeViewItemViewModel _parent;
        private List<TreeViewItemViewModel> _childern;


        public TreeViewItemViewModel(TreeViewItemViewModel parent, string name)
        {
            _parent = parent;
            _name = name;

            _childern = new List<TreeViewItemViewModel>();
        }



        public string Name
        {
            get
            {
                return _name;
            }
        }

        public TreeViewItemViewModel Parent
        {
            get
            {
                return _parent;
            }
        }

        public List<TreeViewItemViewModel> Children
        {
            get
            {
                return _childern;
            }
        }

        public void AddChild(TreeViewItemViewModel c)
        {
            _childern.Add(c);
            RaisePropertyChanged(nameof(Children));
        }

    }

那么您只需要:

            <TreeView Grid.Row="1" Grid.Column="0" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
              ItemsSource="{Binding TreeItemsUserSearch}"
              IsEnabled="{Binding TreeEnabled}">
                <i:Interaction.Behaviors>
                    <b:TreeViewSelectedItemBehavior SelectedItem="{Binding SelectedTreeItemUserSearch}" />
                </i:Interaction.Behaviors>

                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                        <TextBlock Text="{Binding Name}" />
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>

在ViewModel中,您只需要具备以下条件:

private List<TreeViewItemViewModel> _treeItemsUserSearch;


public List<TreeViewItemViewModel> TreeItemsUserSearch
{
    get
    {
        return _treeItemsUserSearch;
    }
}

然后您可以创建所需的每种结构