2011-01-05 92 views
2

我試圖在綁定到CollectionViewSource的WPF中創建一個TreeView。我在CollectionViewSource中創建組,並在XAML中設置HierarchicalDataTemplate以正確顯示TreeView。WPF TreeView動態分組

在我的ViewModel中,我有一個方法來改變CollectionViewSource的分組,並且一切似乎都很好。我唯一的問題是顯示沒有任何分組的CollectionViewSource。

有誰知道如何設計模板以適應CollectionViewSource沒有分組的場景,但是也可以容納帶分組的CollectionViewSource?

更新 我已經創建了一些示例代碼來更好地描述我在做什麼。 DataTemplateSelector在應用程序啓動時工作,但當用戶從組合框中選擇不同的分組選項時,我無法弄清楚如何重新啓動DataTemplate選擇器。下面是我的示例代碼

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

背後

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

回答

-1

也許this代碼將有助於不清楚。

+0

沒有太多的幫助,但我要編輯原始問題以包含示例代碼。 – Amit 2011-01-06 22:41:57

0

您可以通過創建一個綁定到區間變量的Converter來重寫ItemTemplateSelector。

+0

感謝喬爾 - 我是轉換器的新手,所以我想知道我應用了什麼轉換器? – Amit 2011-01-07 01:54:40

+0

我只是看了一遍你的代碼,我想我已經部​​分錯了。你綁定到Selector,但你只在InitializeComponent中設置一次,因此綁定到你的選擇器只發生一次。您需要將ItemTemplateSelector綁定到組合框的SelectedItem,以便在選擇不同的東西時更改它。這是轉換器可以提供幫助的地方。轉換器將允許您將組合框中的對象轉換爲DataTemplateSelector。 – 2011-01-07 04:35:44