2011-01-05 18 views
2

Ich versuche, ein TreeView in WPF zu erstellen, das an eine CollectionViewSource gebunden ist. Ich erstelle Gruppen in der CollectionViewSource und habe das HierarchicalDataTemplate-Setup in XAML, um das TreeView ordnungsgemäß anzuzeigen.WPF-TreeView-dynamische Gruppierung

In meinem ViewModel habe ich eine Methode, um die Gruppierung der CollectionViewSource zu ändern und alles scheint gut zu funktionieren. Das einzige Problem, das ich habe, zeigt die CollectionViewSource ohne irgendeine Gruppierung an.

Kann jemand die Vorlage entwerfen, um ein Szenario unterzubringen, in dem die CollectionViewSource keine Gruppierungen hat, aber auch eine CollectionViewSource mit Gruppierungen aufnehmen kann?

Aktualisieren Ich habe einige Beispielcode erstellt, um besser zu beschreiben, was ich mache. Der DataTemplateSelector funktioniert, wenn die Anwendung gestartet wird, aber ich kann nicht herausfinden, wie der DataTemplate-Selektor erneut ausgelöst wird, wenn der Benutzer eine andere Gruppierungsoption aus der Combobox auswählt. Unten ist mein Beispielcode

<Window 
x:Class="TreeViewGroupTest.MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="clr-namespace:TreeViewGroupTest" 
Title="WindowsApplication1" 
Height="Auto" Width="300"> 

<Window.Resources> 

    <local:SchoolTemplateSelector x:Key="schoolTemplateSelector" /> 

    <HierarchicalDataTemplate x:Key="BasicList" ItemsSource="{Binding TeachersBy.Source}"> 
     <StackPanel> 
      <TextBlock Text="{Binding Name}" /> 
      <ComboBox SelectionChanged="ComboBox_SelectionChanged" ItemsSource="{Binding GroupByList}" /> 
     </StackPanel> 
     <HierarchicalDataTemplate.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Last}" /> 
      </DataTemplate> 
     </HierarchicalDataTemplate.ItemTemplate> 
    </HierarchicalDataTemplate> 

    <HierarchicalDataTemplate x:Key="GroupList" ItemsSource="{Binding TeachersBy.View.Groups}"> 
     <StackPanel> 
      <TextBlock Text="{Binding Name}" /> 
      <ComboBox SelectionChanged="ComboBox_SelectionChanged" ItemsSource="{Binding GroupByList}" /> 
     </StackPanel> 
     <HierarchicalDataTemplate.ItemTemplate> 
      <HierarchicalDataTemplate ItemsSource="{Binding Items}"> 
       <TextBlock Text="{Binding Name}" /> 
       <HierarchicalDataTemplate.ItemTemplate> 
        <DataTemplate> 
         <TextBlock Text="{Binding Last}" /> 
        </DataTemplate> 
       </HierarchicalDataTemplate.ItemTemplate> 
      </HierarchicalDataTemplate> 
     </HierarchicalDataTemplate.ItemTemplate> 
    </HierarchicalDataTemplate> 
</Window.Resources> 

<StackPanel>   
    <TreeView ItemsSource="{Binding Schools}" ItemTemplateSelector="{Binding schoolTemplateSelector}" /> 
</StackPanel> 

und der Code hinter

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls;  
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Collections.ObjectModel; 

namespace TreeViewGroupTest 
{ 
/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
public partial class MainWindow : Window 
{ 
    public ObservableCollection<School> Schools { get; set; } 
    public SchoolTemplateSelector schoolTemplateSelector { get; set; } 

    private string group = "Subject"; 
    public string GroupByChoice { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 

     GroupByChoice = "Subject"; 

     Schools = new ObservableCollection<School> { 
      new School 
      { 
       Name = "Apple", 
       Teachers = new ObservableCollection<Teacher> { 
        new Teacher { Last = "Alpha", Subject = "Math" , Grade = "9th" }, 
        new Teacher { Last = "Beta", Subject = "English" , Grade = "9th" }, 
        new Teacher { Last = "Charlie", Subject = "Math" , Grade = "9th" }, 
        new Teacher { Last = "Delta", Subject = "English" , Grade = "10th" }, 
        new Teacher { Last = "Echo", Subject = "Math" , Grade = "10th" }, 
        new Teacher { Last = "Foxtrot", Subject = "English" , Grade = "10th" }, 
       } 
      }, 
      new School 
      { 
       Name = "Microsoft", 
       Teachers = new ObservableCollection<Teacher> { 
        new Teacher { Last = "Alpha", Subject = "Math" , Grade = "9th" }, 
        new Teacher { Last = "Beta", Subject = "English" , Grade = "9th" }, 
        new Teacher { Last = "Charlie", Subject = "Math" , Grade = "9th" }, 
        new Teacher { Last = "Delta", Subject = "English" , Grade = "10th" }, 
        new Teacher { Last = "Echo", Subject = "Math" , Grade = "10th" }, 
        new Teacher { Last = "Foxtrot", Subject = "English" , Grade = "10th" }, 
       } 
      }, 
     }; 

     Schools[0].SetTeacher(); ; 
     Schools[1].GroupBy("Subject"); 
     Schools[1].TeachersBy.View.Refresh(); 

     this.DataContext = this; 

     schoolTemplateSelector = new SchoolTemplateSelector(); 

    } 

    private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     string prop = e.AddedItems[0].ToString(); 

     if (prop != "None") 
     { 
      foreach (School s in Schools) 
      { 
       s.GroupBy(prop); 
      } 
     } 
     else 
     { 
      foreach (School s in Schools) 
      { 
       s.TeachersBy.GroupDescriptions.Clear(); 
      } 
     }  

     //The DataTemplateSelector should fire now... 
    } 
} 

public class School 
{ 
    public string Name { get; set; } 

    public ObservableCollection<Teacher> Teachers { get; set; } 

    public CollectionViewSource TeachersBy { get; set; } 

    public ObservableCollection<String> GroupByList { get; set; } 

    public School() 
    { 
     Teachers = new ObservableCollection<Teacher>(); 
     TeachersBy = new CollectionViewSource(); 

     GroupByList = new ObservableCollection<string> { 
      "None", "Subject", "Grade" 
     }; 
    } 

    public void SetTeacher() 
    { 
     TeachersBy.Source = Teachers; 
    } 

    public void GroupBy(string propertyName) 
    { 
     TeachersBy.Source = Teachers; 
     TeachersBy.GroupDescriptions.Clear(); 
     TeachersBy.GroupDescriptions.Add(new PropertyGroupDescription(propertyName)); 
     TeachersBy.View.Refresh(); 
    } 

} 

public class Teacher 
{ 
    public string Last { get; set; } 
    public string Subject { get; set; } 
    public string Grade { get; set; } 
    public Teacher() { } 
} 

public class SchoolTemplateSelector : DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     FrameworkElement element = container as FrameworkElement; 

     if (item is School && (item as School).TeachersBy.GroupDescriptions.Count > 0) 
     { 
      return 
       element.FindResource("GroupList") 
         as DataTemplate; 
     } 
     else 
     { 
      return 
       element.FindResource("BasicList") 
         as DataTemplate; 
     } 
    } 
} 
} 

Antwort

-1

Vielleicht this nicht sicher helfen.

+0

War nicht zu viel Hilfe, aber ich werde die ursprüngliche Frage bearbeiten, um Beispielcode einzuschließen. – Amit

0

Sie können den ItemTemplateSelector erneut aktivieren, indem Sie einen Converter erstellen, der an eine Intervallvariable gebunden ist.

+0

Danke Joel - Ich bin neu in Converters, also frage ich mich, wofür ich den Converter anwende? – Amit

+0

Ich habe mir deinen Code noch einmal angeschaut, ich glaube ich habe es teilweise falsch verstanden. Sie binden sich an den Selektor, aber Sie setzen diesen nur einmal in InitializeComponent, daher erfolgt die Bindung an Ihren Selektor nur einmal. Sie müssen den ItemTemplateSelector an das SelectedItem der Combobox binden, damit es sich ändert, wenn Sie etwas anderes auswählen. Hier würde der Konverter helfen. Der Konverter würde es Ihnen ermöglichen, von den Objekten in der Combobox zu einem DataTemplateSelector zu konvertieren. –