CollectionViewSource にバインドされた WPF で TreeView を作成しようとしています。CollectionViewSource でグループを作成し、XAML で HierarchicalDataTemplate をセットアップして TreeView を適切に表示します。
私のViewModelには、CollectionViewSourceのグループ化を変更する方法があり、すべてうまく機能しているようです。私が持っている唯一の問題は、グループ化せずに CollectionViewSource を表示することです。
CollectionViewSource にグループ化がなく、グループ化された CollectionViewSource にも対応できるシナリオに対応するようにテンプレートを設計する方法を知っている人はいますか?
更新 私がやっていることをよりよく説明するために、いくつかのサンプルコードを作成しました。アプリの起動時に DataTemplateSelector が機能しますが、ユーザーがコンボボックスから別のグループ化オプションを選択したときに DataTemplate Selector を再起動する方法がわかりません。以下は私のサンプルコードです
<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;
}
}
}
}