代码之家  ›  专栏  ›  技术社区  ›  longday

WPF TreeView HierarchycalDataTemplate-绑定到具有多个子集合的对象

  •  52
  • longday  · 技术社区  · 16 年前

    我想找一份工作 TreeView 绑定我的集合,以便所有组显示嵌套组,每个组显示条目。

    HierarchicalDataTemplate 所以 树景 是否同时处理子组和条目集合?

    组显示子组和条目:

    Example:
    Group1
    --Entry
    --Entry
    Group2
    --Group4
    ----Group1
    ------Entry
    ------Entry
    ----Entry
    ----Entry
    --Entry
    --Entry
    Group3
    --Entry
    --Entry
    


    物体:


    namespace TaskManager.Domain
    {
        public class Entry
        {
            public int Key { get; set; }
            public string Name { get; set; }
        }
    }
    
    namespace TaskManager.Domain
    {
        public class Group
        {
            public int Key { get; set; }
            public string Name { get; set; }
    
            public IList<Group> SubGroups { get; set; }
            public IList<Entry> Entries { get; set; }
        }
    }
    


    namespace DrillDownView
    {
        public class TestData
        {
    
            public IList<Group> Groups = new List<Group>();
    
            public void Load()
            {
                Group grp1 = new Group() { Key = 1, Name = "Group 1", SubGroups = new List<Group>(), Entries = new List<Entry>() };
                Group grp2 = new Group() { Key = 2, Name = "Group 2", SubGroups = new List<Group>(), Entries = new List<Entry>() };
                Group grp3 = new Group() { Key = 3, Name = "Group 3", SubGroups = new List<Group>(), Entries = new List<Entry>() };
                Group grp4 = new Group() { Key = 4, Name = "Group 4", SubGroups = new List<Group>(), Entries = new List<Entry>() };
    
                //grp1
                grp1.Entries.Add(new Entry() { Key=1, Name="Entry number 1" });
                grp1.Entries.Add(new Entry() { Key=2, Name="Entry number 2" });
                grp1.Entries.Add(new Entry() { Key=3,Name="Entry number 3" });
    
                //grp2
                grp2.Entries.Add(new Entry(){ Key=4, Name = "Entry number 4"});
                grp2.Entries.Add(new Entry(){ Key=5, Name = "Entry number 5"});
                grp2.Entries.Add(new Entry(){ Key=6, Name = "Entry number 6"});
    
                //grp3
                grp3.Entries.Add(new Entry(){ Key=7, Name = "Entry number 7"});
                grp3.Entries.Add(new Entry(){ Key=8, Name = "Entry number 8"});
                grp3.Entries.Add(new Entry(){ Key=9, Name = "Entry number 9"});
    
                //grp4
                grp4.Entries.Add(new Entry(){ Key=10, Name = "Entry number 10"});
                grp4.Entries.Add(new Entry(){ Key=11, Name = "Entry number 11"});
                grp4.Entries.Add(new Entry(){ Key=12, Name = "Entry number 12"});
    
                grp4.SubGroups.Add(grp1);
                grp2.SubGroups.Add(grp4);
    
                Groups.Add(grp1);
                Groups.Add(grp2);
                Groups.Add(grp3);
            }
        }
    }
    

    XAML:


    <Window x:Class="DrillDownView.Window2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:TaskManager.Domain;assembly=TaskManager.Domain"
            Title="Window2" Height="300" Width="300">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
    
            <TreeView Name="GroupView" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding}">
                <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type local:Group}" ItemsSource="{Binding SubGroups}">
                        <TextBlock Text="{Binding Path=Name}" />
                    </HierarchicalDataTemplate>
                    <HierarchicalDataTemplate DataType="{x:Type local:Entry}" ItemsSource="{Binding Entries}">
                        <TextBlock Text="{Binding Path=Name}" />
                    </HierarchicalDataTemplate>
                </TreeView.Resources>
            </TreeView>
        </Grid>
    </Window>
    


    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();
            LoadView();
        }
    
        private void LoadView()
        {
            TestData data = new TestData();
            data.Load();
            GroupView.ItemsSource = data.Groups;
        }
    }
    
    4 回复  |  直到 9 年前
        1
  •  115
  •   Soleil    7 年前

    A. HierarchicalDataTemplate

    e、 g.(如果不能使组和条目都从公共节点类型派生)

    public class Group{ ....
            public IList<object> Items
            {
                get
                {
                    IList<object> childNodes = new List<object>();
                    foreach (var group in this.SubGroups)
                        childNodes.Add(group);
                    foreach (var entry in this.Entries)
                        childNodes.Add(entry);
    
                    return childNodes;
                }
            }
    

    下一步,你不需要 层次数据模板 用于条目,因为条目没有子项。因此需要更改XAML以使用new Items属性和 DataTemplate

    <TreeView Name="GroupView" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:Group}" ItemsSource="{Binding Items}">
                <TextBlock Text="{Binding Path=Name}" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type local:Entry}" >
                <TextBlock Text="{Binding Path=Name}" />
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>
    

    下面是它的样子。 Screenshot of Output

        2
  •  11
  •   kiwipom    16 年前

    我想你在那里的大部分时间。。。只要稍加修改,你就可以很容易地完成这项工作。。。

    我建议您创建一个基本抽象类(或一个接口,无论您喜欢哪个),并为Group和Entry类继承/实现它。。。

    public ObservableCollection<ITreeViewItem> Children { get; set; }
    

    ^此时,您可以决定是替换子组和条目列表,还是仅仅将它们附加在一起并在属性getter中返回它们。。。

    现在,您只需使用组或条目对象填充子集合,然后 HierarchicalDataTemplate

    最后一个想法是,如果条目始终是树的“底层”(即没有子项),则不需要定义 层次数据模板 对于Entry对象,一个 DataTemplate

    希望这有帮助:)

        3
  •  10
  •   Matthew    15 年前

    下面是Gishu答案的另一个实现,它返回 IEnumerable 而不是 IList ,并利用 yield

    public class Group
    {
        ...
    
        public IEnumerable<object> Items
        {
            get
            {
                foreach (var group in this.SubGroups)
                    yield return group;
                foreach (var entry in this.Entries)
                    yield return entry;
            }
        }
    }
    
        4
  •  3
  •   Mozart    6 年前

    在为同一问题寻找解决方案时,这篇文章帮助了我: http://blog.pmunin.com/2012/02/xaml-binding-to-compositecollection.html