2011-01-05 4 views
2

Je tente de créer un TreeView dans WPF qui est lié à une CollectionViewSource. Je crée des groupes dans CollectionViewSource et ai l'installation HierarchicalDataTemplate dans le XAML pour afficher le TreeView correctement.WPF TreeView Dynamic Grouping

Dans mon ViewModel j'ai une méthode pour modifier le regroupement de la CollectionViewSource et tout semble bien fonctionner. Le seul problème que j'ai est d'afficher le CollectionViewSource sans aucun groupement.

Est-ce que quelqu'un sait comment concevoir le modèle pour prendre en charge un scénario dans lequel CollectionViewSource ne possède aucun regroupement, mais peut également accueillir une CollectionViewSource avec des regroupements?

Mise à jour J'ai créé un exemple de code pour mieux décrire ce que je fais. Le DataTemplateSelector fonctionne lorsque l'application démarre mais je n'arrive pas à comprendre comment redéclencher le sélecteur DataTemplate lorsque l'utilisateur sélectionne une option de regroupement différente dans la liste déroulante. Ci-dessous mon exemple de code

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

et le code derrière

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

Répondre

-1

Peut-être this aidera pas sûr.

+0

Pas trop d'aide, mais je vais modifier la question initiale pour inclure un exemple de code. – Amit

0

Vous pouvez renommer ItemTemplateSelector en créant un convertisseur lié à une variable d'intervalle.

+0

Merci Joel - Je suis nouveau à Convertisseurs, donc je me demande à quoi est-ce que j'applique le Convertisseur? – Amit

+0

Je viens de regarder à nouveau votre code, je pense que je l'ai partiellement faux. Vous liez le sélecteur, mais vous ne définissez celui-ci qu'une seule fois dans InitializeComponent. Par conséquent, la liaison à votre sélecteur ne se produit qu'une seule fois. Vous devez lier le ItemTemplateSelector à l'objet SelectedItem de la liste déroulante afin qu'il change lorsque vous choisissez quelque chose de différent. C'est là que le convertisseur aiderait. Le convertisseur vous permet de convertir les objets de la liste déroulante en un DataTemplateSelector. –