【问题标题】:HierarchicalDataTemplate Distinct leavesHierarchicalDataTemplate 不同的叶子
【发布时间】:2010-04-13 06:27:28
【问题描述】:

我有一组数据结构如下:

 ItemA.GroupA
 ItemB.GroupA
 ItemC.GroupB
 ItemD.GroupC

我需要像这样在 WPF 树视图中显示数据:

A组

--- 项目A

--- 项目B

B组

--- 项目C

C组

--- 项目D

我可以使用什么 XAML 按不同的值对叶子进行分组?例如,集合中可能有多个项目,它们是 GroupA.ItemA,但是,我只想呈现节点和叶子一次。

【问题讨论】:

    标签: c# wpf hierarchicaldatatemplate


    【解决方案1】:

    我不同意 itowlson 的观点。这不是一个棘手的问题,HierarchicalDataTemplate 就是为这种事情而设计的。在您随意深入研究模式和视图模型以及其他不必要的混淆之前,请考虑您的问题可以通过两个类和一个 Linq GroupBy 语句来解决。

    这是你的课程:

    public class GroupItem
    {
        public string Name
        {
            get;
            private set;
        }
    
        public string Group
        {
            get;
            private set;
        }
    
        public GroupItem(string name, string group)
        {
            Name = name;
            Group = group;
        }
    }
    
    public class Group
    {
        public IEnumerable<GroupItem> Children
        {
            get;
            set;
        }
    
        public string Name
        {
            get;
            private set;
        }
    
        public Group(string name)
        {
            Name = name;
        }
    }
    

    到目前为止,一切都很好。你有两个简单的类来保存所有必要的数据。名称和组存储为字符串。 Group 有一个 GroupItem 集合。现在查看Window 中的代码:

    public partial class DistinctLeaves : Window
    {
        public ObservableCollection<GroupItem> Items
        {
            get;
            set;
        }
    
        public IEnumerable<Group> Groups
        {
            get;
            set;
        }
    
        public DistinctLeaves()
        {
            Items = new ObservableCollection<GroupItem>();
    
            Items.Add(new GroupItem("Item A", "Group A"));
            Items.Add(new GroupItem("Item B", "Group A"));
            Items.Add(new GroupItem("Item C", "Group B"));
            Items.Add(new GroupItem("Item D", "Group C"));
    
            Groups = Items.
                GroupBy(i => i.Group).
                Select(g => new Group(g.Key) { Children = g });
    
            InitializeComponent();
        }
    }
    

    再一次,除了 group-by 行之外,这都是样板文件。该声明值得进一步调查。这将根据它们的Group 属性对您的项目集合进行分组。将项目分组后,然后创建Group 类的新实例。传入组的名称属性(这是键),并将子项设置为组本身,然后ta-da!

    最后,这是Window 的XAML,它使用HierarchicalDataTemplate

    <Window x:Class="TestWpfApplication.DistinctLeaves"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="DistinctLeaves" Height="300" Width="300"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <TreeView ItemsSource="{Binding Groups}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}"/>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
    

    结果如下:

    alt text http://img339.imageshack.us/img339/8555/distinctleaves.jpg

    【讨论】:

    • Wouldn't using ItemsSource="{Binding Children}" 在运行时抛出绑定异常,因为叶子视图模型没有这样的属性?
    • 可能是的,但由于这个原因,绑定会静默失败。性能损失可以忽略不计,因为这种绑定解决方案每组只应发生一次。如果这是不可接受的,您可以将 Children 属性添加到叶子视图模型并创建一个空列表。
    【解决方案2】:

    您将无法在 XAML 中做到这一点,至少不能以任何自然的方式。更好的方法是引入 视图模型 - 一个以视图友好的方式表示数据的类,以便您可以保持 XAML 简单和自然。

    因此,在您的情况下,您将拥有一个包装您的 ItemX 集合并公开组及其不同成员的类:

    public class MyItemsViewModel
    {
      public IList<MyGroupViewModel> Groups { get; }
    }
    
    public class MyGroupViewModel
    {
      public string GroupName { get; }
      public IList<MyItem> DistinctItems { get; }
    }
    

    然后,您的 HierarchicalDataTemplate 几乎会自动失效。另一个好处是,由于您的视图模型类只是数据对象,您可以将它们置于自动化测试之下,而复杂的 XAML 则需要手动测试。

    【讨论】:

    • 虽然这在技术上并没有错——他确实应该已经为这种事情定义了一个视图模型类——我认为这没有抓住问题的重点。他不是在问他应该如何修复他的代码以使 MVVM 正确,而是在问他如何组织他现有的数据来代表不同的组。
    • 查理:我实际上认为我们非常同意——也许我的回答很糟糕,但我们都说 HierarchicalDataTemplate 是正确的解决方案并且使用起来非常简单提供 数据结构正确。我已经使用术语“视图模型”来表示视图友好的数据结构,您认为这是混淆 - 但是我们提出的数据结构是相同的,我同意您对该结构的实现。区别在于术语,而不是实践:如果我对“视图模型”一词的使用显得沉重或令人生畏,我深表歉意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    • 1970-01-01
    • 2022-08-21
    • 2021-09-03
    相关资源
    最近更新 更多