2011-01-05 4 views
2

저는 CollectionViewSource에 바인딩 된 WPF에서 TreeView를 만들려고합니다. CollectionViewSource에 그룹을 만들고 TreeView를 제대로 표시하기 위해 XAML에서 HierarchicalDataTemplate을 설정해야합니다.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

0

간격 변수에 바인딩 된 변환기를 만들어 ItemTemplateSelector를 다시 열 수 있습니다.

+0

Joel 감사합니다. Converters를 처음 사용 했으므로 변환기를 적용 할 대상은 무엇입니까? – Amit

+0

방금 ​​코드를 다시 보았습니다. 부분적으로 잘못 생각한 것 같습니다. Selector에 바인딩하고 있지만 InitializeComponent에서 한 번만 설정하므로 선택기에 대한 바인딩은 한 번만 발생합니다. ItemTemplateSelector를 콤보 상자의 SelectedItem에 바인딩하여 다른 항목을 선택할 때 변경되도록해야합니다. 컨버터가 도움이 될 곳입니다. 변환기를 사용하면 콤보 상자의 개체를 DataTemplateSelector로 변환 할 수 있습니다. –