2015-10-20 115 views
-1

我一直在瀏覽教程和閱讀一些關於樹視圖中多種類型的文章。不過,我還沒有遇到過一個教程,它解釋瞭如何構建或處理一個包含多個嵌套的不同節點類型的treeview。例如,考慮一個典型的文件夾結構。一個文件夾可以包含文件和文件夾,其中的文件夾可以包含更多的文件和文件夾。所以我試圖把它分解成一個簡單的解決方案,希望有人能夠修改/向我解釋如何讓一個家庭嵌套在另一個家庭內,如下圖所示。到其他堆棧溢出的鏈接並不能解釋INode接口如何工作的細節。與多種類型的WPF樹視圖

enter image description here

從我讀過什麼,我知道我需要三個等級。

  1. 第1類:FamilyNode

    • 這個類包含3名屬性成員名,父
  2. 二級:FamilyMember

    • 這個類包含2個屬性名稱,年齡
  3. 3類:INODE

    • 這個類包含1個屬性名稱。爲這個類創建一個INode接口將允許我們在Treeview中創建您想要的每個內容項的不同實現。這個類的一個例子就是喜歡這樣。我相信

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

下面是什麼在上面下的「當前」圖片中看到的代碼。我知道這不是以最好的方式組織起來的,我只是希望得到一個簡單的例子和​​解釋。我希望你們能夠提供幫助,它爲此耗費時間進行研究。我只能圍繞如何製作可能是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> 
+0

我不能爲WPF說話,但在的WinForms,你可以將標籤分配到每個節點類型,並根據其作用。 –

+0

是的,這並不適用於wpf – JokerMartini

+2

你能解釋[這個答案](http://stackoverflow.com/a/33195027/643085)不能滿足你的需求嗎?在我看來,你在這裏提出的一切都已經在你以前的文章中得到了回答。 –

回答

1

我想出的解決方案與朋友交談,想我會在這裏發佈。

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; } 
    } 
}