WPFプログラミング備忘録

WPF DataGridの行をグループ化する

WPF

はじめに

この記事ではDataGridの行を条件によってグループ化することを確認しています。

フォルダ構成は以下のとおりです。

開発環境は以下のとおりです。

オペレーティングシステムWindows10 x64
Visual StudioMicrosoft Visual Studio Community 2019 Version 16.11.2
.NET Framework4.7.2

サンプルプログラムの動作仕様

RadioButtonで学部と性別によってグループ化できるようにします。

グループ化を解除したときのウィンドウの状態は以下のとおりです。

グループ化を解除

学部によってグループ化したときのウィンドウの状態は以下のとおりです。

学部によってグループ化

性別によってグループ化したときのウィンドウの状態は以下のとおりです。

性別によってグループ化

グループ化するプログラムの実装

モデルに相当する学生クラスは以下のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfDataGridGrouping
{
    /// <summary>
    /// 学生を表すクラス
    /// </summary>
    public class Student
    {
        public int Number { get; set; }
        public string Name { get; set; }
        public string Department { get; set; } // 学部
        public string Gender { get; set; } // 性別
        public string Memo { get; set; }
    }
}

XAMLは以下のとおりです。

<Window x:Class="WpfDataGridGrouping.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:WpfDataGridGrouping"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="500">
    <StackPanel>
        <DataGrid x:Name="dg" AutoGenerateColumns="False" CanUserAddRows="False" 
                  HorizontalScrollBarVisibility="Hidden" CanUserSortColumns="False" SelectionUnit="FullRow">
            <DataGrid.Columns>
                <DataGridTextColumn Header="学籍番号" Binding="{Binding Number}" IsReadOnly="True"/>
                <DataGridTextColumn Header="氏名" Binding="{Binding Name}" IsReadOnly="True"/>
                <DataGridTextColumn Header="学部" Binding="{Binding Department}" IsReadOnly="True"/>
                <DataGridTextColumn Header="性別" Binding="{Binding Gender}" IsReadOnly="True"/>
                <DataGridTextColumn Header="メモ" Binding="{Binding Memo}" Width="*" IsReadOnly="True"/>
            </DataGrid.Columns>
            <DataGrid.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Margin" Value="0,0,0,10"/>
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Expander IsExpanded="True" Background="Navy" Foreground="White">
                                            <Expander.Header>
                                                <StackPanel Orientation="Horizontal">
                                                    <TextBlock Text="{Binding Name}" Margin="5,0,5,0"/>
                                                    <StackPanel Orientation="Horizontal">
                                                        <TextBlock Text="("/>
                                                        <TextBlock Text="{Binding ItemCount}"/>
                                                        <TextBlock Text="人)"/>
                                                    </StackPanel>
                                                </StackPanel>
                                            </Expander.Header>
                                            <Expander.Content>
                                                <ItemsPresenter />
                                            </Expander.Content>
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </DataGrid.GroupStyle>
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="Foreground" Value="Black"/>
                    <Setter Property="Background" Value="White"/>
                </Style>
            </DataGrid.RowStyle>
        </DataGrid>
        <GroupBox Header="グループ化" HorizontalAlignment="Right">
            <StackPanel Orientation="Horizontal">
                <RadioButton Content="なし" GroupName="grouping" Margin="0,4,8,0" IsChecked="True" Checked="OnGroupingNone"/>
                <RadioButton Content="学部" GroupName="grouping" Margin="0,4,8,0" Checked="OnGroupingByDepartment"/>
                <RadioButton Content="性別" GroupName="grouping" Margin="0,4,8,0" Checked="OnGroupingByGender"/>
            </StackPanel>
        </GroupBox>
    </StackPanel>
</Window>

DataGridと3つのRadioButtonを配置しています。

RadioButton(なし)を選択するとグループ化を解除します。

RadioButton(学部)を選択すると学部によってグループ化します。

RadioButton(性別)を選択すると性別によってグループ化します。

Expanderを使用してグループ化したときのスタイルを定義しています。

コードビハインドは以下のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 WpfDataGridGrouping
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Students = new ObservableCollection<Student>
            {
                new Student
                {
                    Number = 1,
                    Name = "山田太郎",
                    Department = "政治経済学部",
                    Gender = "男"
                },

                new Student
                {
                    Number = 2,
                    Name = "鈴木花子",
                    Department = "文学部",
                    Gender = "女"
                },

                new Student
                {
                    Number = 3,
                    Name = "青木次郎",
                    Department = "法学部",
                    Gender = "男"
                },

                new Student
                {
                    Number = 4,
                    Name = "井上三郎",
                    Department = "文学部",
                    Gender = "男"
                },

                new Student
                {
                    Number = 5,
                    Name = "臼井由佳",
                    Department = "政治経済学部",
                    Gender = "女"
                },

                new Student
                {
                    Number = 6,
                    Name = "寺尾四郎",
                    Department = "政治経済学部",
                    Gender = "男"
                },

                new Student
                {
                    Number = 7,
                    Name = "中村香",
                    Department = "文学部",
                    Gender = "女"
                },
            };

            dg.ItemsSource = Students;
        }

        public ObservableCollection<Student> Students { get; set; }

        private void GroupingByPropertyName(string propertyName)
        {
            var cv = CollectionViewSource.GetDefaultView(dg.ItemsSource);

            if (cv != null && cv.CanGroup)
            {
                cv.GroupDescriptions.Clear();

                cv.GroupDescriptions.Add(new PropertyGroupDescription(propertyName));
            }
        }

        /// <summary>
        /// グループ化を解除する
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnGroupingNone(object sender, RoutedEventArgs e)
        {
            var cv = CollectionViewSource.GetDefaultView(dg.ItemsSource);

            if (cv != null && cv.CanGroup)
            {
                cv.GroupDescriptions.Clear();
            }
        }

        /// <summary>
        /// 学部によってグループ化する
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnGroupingByDepartment(object sender, RoutedEventArgs e)
        {
            GroupingByPropertyName("Department");
        }

        /// <summary>
        /// 性別によってグループ化する
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnGroupingByGender(object sender, RoutedEventArgs e)
        {
            GroupingByPropertyName("Gender");
        }
    }
}

RadioButtonがチェックされる度にICollectionViewのGroupDescriptionsプロパティでグループ化をしたり解除したりしています。

>> ICollectionView.GroupDescriptionsプロパティ

>> PropertyGroupDescriptionクラス

グループ化の詳細については以下をご確認ください。

方法: DataGrid コントロールでデータをグループ化、並べ替え、およびフィルター処理する - WPF .NET Framework
ビューでのデータのグループ化、並べ替え、フィルター処理をサポートする CollectionView に、Windows Presentation Foundation の DataGrid コントロールをバインドする方法について学習します。

今回はDataGridの行を条件によってグループ化することを確認しました。

DataGridの行を条件によってフィルタリングする方法は以下の記事で確認しています。

>> WPF DataGridの行をフィルタリングする

以上です。

コメント