具有多种类型的wpf treeview

wpf treeview with multiple types

我一直在浏览教程并在线阅读一些关于树视图中多种类型的文章。但是,我还没有遇到解释如何构建或处理包含多个嵌套的不同节点类型的树视图的教程。例如,考虑一个典型的文件夹结构。文件夹中可以包含文件和文件夹,文件夹中可以包含更多文件和文件夹。所以我试图将其分解为一个简单的解决方案,希望有人可以 modify/explain 告诉我如何将一个家庭嵌套在另一个家庭中,如下图所示。 link to the other stack overflow 并没有详细解释INode接口是如何工作的。

根据我的阅读,我知道我需要三个 classes。

  1. Class 1: 家庭节点

    • 此 class 包含 3 个属性 Members、Name、Parent
  2. Class 2: 家庭成员

    • 此 class 包含 2 个属性名称、年龄
  3. Class 3: INode

    • 此 class 包含 1 属性 个名称。为此 class 创建一个 INode 接口将允许我们为您在 Treeview 中想要的每个内容项创建不同的实现。这个 class 的一个例子就像这样我相信...

public interface INode
{
     string Name { get; }
     string Path { get; }
}

下面是上图中 'current' 下的代码。我知道它没有以最好的方式组织起来,我只是想得到一个简单的例子和​​解释。我希望你们能帮忙,为此研究很费时间。我可以全神贯注于如何创建一个节点集合,这些节点可以是 Family 或 FamilyMember 类型,然后开始构建树视图。感谢大家的帮助。

ViewModel.cs

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

    namespace WpfApplication1
    {
        public class ViewModel : INotifyPropertyChanged
        {
            private ObservableCollection<Family> families;
            public ObservableCollection<Family> Families
            {
                get { return families; }
                set
                {
                    families = value;
                    NotifyPropertyChanged("Families");
                }
            }

            public ViewModel()
            {
                // FAMILIES
                Families = new ObservableCollection<Family>();

                Family family1 = new Family() { Name = "The Doe's" };
                family1.Members.Add(new FamilyMember() { Name = "John Doe", Age = 42 });
                family1.Members.Add(new FamilyMember() { Name = "Jane Doe", Age = 39 });
                family1.Members.Add(new FamilyMember() { Name = "Sammy Doe", Age = 13 });
                Families.Add(family1);

                Family family2 = new Family() { Name = "The Moe's" };
                family2.Members.Add(new FamilyMember() { Name = "Mark Moe", Age = 31 });
                family2.Members.Add(new FamilyMember() { Name = "Norma Moe", Age = 28 });
                Families.Add(family2);
            }

            public event PropertyChangedEventHandler PropertyChanged;

            public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

        public class Family
        {
            public Family()
            {
                this.Members = new ObservableCollection<FamilyMember>();
            }

            public string Name { get; set; }
            public ObservableCollection<FamilyMember> Members { get; set; }
        }

        public class FamilyMember
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }

MainWindow.Xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:self="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="305"
        WindowStartupLocation="CenterScreen">

    <Window.DataContext>
        <self:ViewModel/>
    </Window.DataContext>

    <Grid>
        <TreeView Name="trvFamilies" ItemsSource="{Binding Families}" Grid.Row="1" Grid.ColumnSpan="2">
            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type self:Family}" ItemsSource="{Binding Members}">
                    <StackPanel Orientation="Horizontal">
                        <Label VerticalAlignment="Center" FontFamily="WingDings" Content="1"/>
                        <TextBlock Text="{Binding Name}" />
                    </StackPanel>
                </HierarchicalDataTemplate>
                <DataTemplate DataType="{x:Type self:FamilyMember}">
                    <StackPanel Orientation="Horizontal">
                        <Label VerticalAlignment="Center" FontFamily="WingDings" Content="2"/>
                        <TextBlock Text="{Binding Name}" />
                    </StackPanel>
                </DataTemplate>
            </TreeView.Resources>
        </TreeView>
    </Grid>

</Window>

我想出了与朋友交谈的解决方案,我想我会 post 在这里。

ViewModel.cs

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfApplication1
{
    public class ViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<INode> families;
        public ObservableCollection<INode> Families
        {
            get { return families; }
            set
            {
                families = value;
                NotifyPropertyChanged("Families");
            }
        }

        public ViewModel()
        {
            // FAMILIES
            Families = new ObservableCollection<INode>();

            Family family1 = new Family() { Name = "The Doe's" };
            family1.Members.Add(new FamilyMember() { Name = "John Doe", Age = 42 });
            family1.Members.Add(new FamilyMember() { Name = "Jane Doe", Age = 39 });
            family1.Members.Add(new FamilyMember() { Name = "Sammy Doe", Age = 13 });
            Families.Add(family1);

            Family family2 = new Family() { Name = "The Moe's" };
            family2.Members.Add(new FamilyMember() { Name = "Mark Moe", Age = 31 });
            family2.Members.Add(new FamilyMember() { Name = "Norma Moe", Age = 28 });
            Families.Add(family2);

            Family family3 = new Family() { Name = "The Dunkin's" };
            family3.Members.Add(new FamilyMember() { Name = "Kevin Dunkin", Age = 31 });
            family3.Members.Add(new FamilyMember() { Name = "Breana Dunkin", Age = 28 });
            family2.Members.Add(family3);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public interface INode
    {
        string Name { get; }
    }

    public class Family : INode
    {
        public Family()
        {
            this.Members = new ObservableCollection<INode>();
        }

        public string Name { get; set; }
        public ObservableCollection<INode> Members { get; set; }
        public Family Parent { get; private set; }
    }

    public class FamilyMember : INode
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}