もくじ
やりたいこと
Grid表示のListViewの中身を、ある列の内容でグループ表示したい。下記のようなイメージ。
やり方
<CollectionViewSource>
を使う。
前回の記事で、xamlにCollectionViewSourceを書いてみたので、今回はコードに書くやり方を試してみる。
(今回はついでにソートも実施)
MainWindow.xaml
<Window x:Class="WpfApp48.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp48"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="200">
<Window.Resources>
<!-- グループのヘッダのスタイルを作成 -->
<DataTemplate x:Key="GroupHeaderTemplate">
<Border Background="#FFCDF2CD">
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<!-- ListViewのItemsSourceをCollectionViewSourceのViewにするのがポイント -->
<ListView Name="MainList" ItemsSource="{Binding UICollectionViewSource.View}">
<!-- グループのヘッダのスタイルを指定(これを指定しないと、グループのヘッダはナシになる) -->
<ListView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource GroupHeaderTemplate}" />
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="機体" DisplayMemberBinding="{Binding MachineName}" Width="80" />
<GridViewColumn Header="パイロット" DisplayMemberBinding="{Binding PilotName}" Width="80" />
</GridView>
</ListView.View>
</ListView>
<Button Grid.Row="1" Content="ボタン" Click="Button_Click"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
namespace WpfApp48
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
// ガンダム情報を格納
public ObservableCollection<MyData> DataList { get; set; } = new ObservableCollection<MyData>();
// ソート/グルーピングに使うCollectionViewSource
CollectionViewSource _UICollectionViewSource;
public CollectionViewSource UICollectionViewSource { get { return _UICollectionViewSource; } set { _UICollectionViewSource = value; } }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
// CollectionViewSourceのソースにDataListを設定
UICollectionViewSource = new CollectionViewSource();
UICollectionViewSource.Source = DataList;
}
// ボタンをおしたらデータの中身を追加
private void Button_Click(object sender, RoutedEventArgs e)
{
DataList.Add(new MyData() { MachineName = "ガンダム", PilotName = "アムロ" });
DataList.Add(new MyData() { MachineName = "シャアザク", PilotName = "シャア" });
DataList.Add(new MyData() { MachineName = "グフ", PilotName = "誰やったっけ?" });
DataList.Add(new MyData() { MachineName = "Zガンダム", PilotName = "カミーユ" });
DataList.Add(new MyData() { MachineName = "ガンダムmk-Ⅱ", PilotName = "アムロ" });
DataList.Add(new MyData() { MachineName = "ジ・オ", PilotName = "シロッコ" });
DataList.Add(new MyData() { MachineName = "百式", PilotName = "シャア" });
DataList.Add(new MyData() { MachineName = "ZZガンダム", PilotName = "ジュドー" });
DataList.Add(new MyData() { MachineName = "νガンダム", PilotName = "アムロ" });
//ソートの指定
SortDescription sortDescription;
UICollectionViewSource.SortDescriptions.Clear();
sortDescription = new SortDescription
{
PropertyName = "MachineName",
Direction = ListSortDirection.Ascending
};
UICollectionViewSource.SortDescriptions.Add(sortDescription);
sortDescription = new SortDescription
{
PropertyName = "PilotName",
Direction = ListSortDirection.Ascending
};
UICollectionViewSource.SortDescriptions.Add(sortDescription);
//グループの指定
PropertyGroupDescription groupDescription;
UICollectionViewSource.GroupDescriptions.Clear();
groupDescription = new MyDataGroupDescription
{
// なにでグループを作るか決める
PropertyName = "PilotName"
};
UICollectionViewSource.GroupDescriptions.Add(groupDescription);
UICollectionViewSource.View.Refresh();
}
}
// ガンダム情報クラス
public class MyData
{
public string MachineName { get; set; }
public string PilotName { get; set; }
}
class MyDataGroupDescription : PropertyGroupDescription
{
// データの中身からグループのヘッダに出すものを決める
public override object GroupNameFromItem(object item, int level, System.Globalization.CultureInfo culture)
{
var uiobject = (MyData)item;
return uiobject.PilotName;
}
}
}
参考
こちらのやり方をかなり参考にさせて頂いています。ありがとうございます。