LoginSignup
1
2

More than 1 year has passed since last update.

[WPF/xaml] ListViewをグループ表示/ソート表示する(C#コードで書く)

Last updated at Posted at 2021-06-12

もくじ

やりたいこと

Grid表示のListViewの中身を、ある列の内容でグループ表示したい。下記のようなイメージ。
image.png

やり方

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

参考

こちらのやり方をかなり参考にさせて頂いています。ありがとうございます。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2