wpf treeview with multiple types

2019-08-30 09:27发布

I've been going over tutorials and reading a few articles online about multiple types in treeviews. However I've not come across a tutorial which explains how to build or handle a treeview which contains multiple different node types nested. For example think of a typical folder structure. A folder can contain files and folders within, and the folders within that can contain more files and folders. So I've attempted to break this down into a simple solution hoping someone can modify/explain to me how to get a family nested inside of another family as seen in the image below. The link to the other stack overflow doesn't explain how the INode interface works in detail.

enter image description here

From what i've read i know i'll need three classes.

  1. Class 1: FamilyNode

    • this class contains 3 properties Members, Name, Parent
  2. Class 2: FamilyMember

    • this class contains 2 properties Name, Age
  3. Class 3: INode

    • this class contains 1 property Name. Creating an INode interface for this class will allow us to create different implementations of each content item you wanted in the Treeview. An example of this class would like like this i believe...

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

Below is the code for what's seen in the picture above under 'current'. I know it's not organized out in the best way possible, i'm just looking to get a simple example and explanation. I hope you guys can help, its been time consuming researching for this. I just can wrap my head around how to make a collection of nodes which could be of type Family or FamilyMember to then begin building the treeview. Thanks for the help guys.

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>

1条回答
Emotional °昔
2楼-- · 2019-08-30 10:26

I figured out the solution talking with a friend and figured i would post it here.

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; }
    }
}
查看更多
登录 后发表回答