WPFプログラミング備忘録

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

WPF

はじめに

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

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

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

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

ラジオボタンで性別を選択すると、それぞれの性別の行のみが表示されるようにします。

全てを選択した場合は全行表示します。

全て

男性を選択した場合は男性のみ表示します。

男性

女性を選択した場合は女性のみ表示します。

女性

フィルタリングのプログラムの実装

XAMLは以下のとおりです。

<Window x:Class="WpfDataGridFiltering.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:WpfDataGridFiltering"
        mc:Ignorable="d"
        Title="FilteringRecords" Height="300" Width="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <GroupBox Header="性別選択">
            <StackPanel Orientation="Horizontal">
                <RadioButton x:Name="radioAll" Content="全て" GroupName="genderFilter" Margin="0,4,8,0" IsChecked="True" Checked="OnRadioAllChecked"/>
                <RadioButton x:Name="radioMen" Content="男性" GroupName="genderFilter" Margin="0,4,8,0" Checked="OnRadioMenChecked"/>
                <RadioButton x:Name="radioWomen" Content="女性" GroupName="genderFilter" Margin="0,4,8,0" Checked="OnRadioWomenChecked"/>
            </StackPanel>
        </GroupBox>
        <DataGrid x:Name="Dg"
                  Grid.Row="1"
                  SelectionMode="Single"
                  HeadersVisibility="Column"
                  SelectionUnit="Cell"
                  AutoGenerateColumns="False"
                  CanUserAddRows="False"
                  Margin="0,10,0,0">
            <DataGrid.Columns>
                <DataGridTextColumn Header="番号" Binding="{Binding number}" IsReadOnly="True" Width="50" CanUserSort="False"/>
                <DataGridTextColumn Header="名前" Binding="{Binding name}" IsReadOnly="True" Width="*" CanUserSort="False"/>
                <DataGridTextColumn Header="年齢" Binding="{Binding age}" IsReadOnly="True" Width="60" CanUserSort="False"/>
                <DataGridTextColumn Header="性別" Binding="{Binding gender}" IsReadOnly="True" Width="60" CanUserSort="False"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

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

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

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.ComponentModel;
using System.Collections.ObjectModel;

namespace WpfDataGridFiltering
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            GridRecords.Add(new GridRecord { number = 1, name = "山田 太郎", age = 28, gender = "男" });
            GridRecords.Add(new GridRecord { number = 2, name = "立花 薫", age = 48, gender = "男" });
            GridRecords.Add(new GridRecord { number = 3, name = "鈴木 花子", age = 32, gender = "女" });
            GridRecords.Add(new GridRecord { number = 4, name = "原田 尚美", age = 26, gender = "女" });
            GridRecords.Add(new GridRecord { number = 5, name = "吉川 雅之", age = 21, gender = "男" });
            GridRecords.Add(new GridRecord { number = 6, name = "寺尾 友紀", age = 50, gender = "女" });
            GridRecords.Add(new GridRecord { number = 7, name = "高橋 寛之", age = 33, gender = "男" });

            collectionView = CollectionViewSource.GetDefaultView(GridRecords);

            collectionView.Filter = new Predicate<object>(target =>
            {
                GridRecord gridRecord = target as GridRecord;

                if(gridRecord != null)
                {
                    if(selectGender == SelectedGender.ALL)
                    {
                        return true;
                    } 
                    else if(selectGender == SelectedGender.Men && gridRecord.gender == MEN)
                    {
                        return true;
                    }
                    else if(selectGender == SelectedGender.Women && gridRecord.gender == WOMEN)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                return true;
            });

            Dg.ItemsSource = collectionView;
        }

        public class GridRecord
        {
            public int number { get; set; }
            public string name { get; set; }
            public int age { get; set; }
            public string gender { get; set; }
        }

        private ObservableCollection<GridRecord> GridRecords = new ObservableCollection<GridRecord>();

        private ICollectionView collectionView;

        private enum SelectedGender
        {
            ALL = 0,
            Men,
            Women
        }

        private const string MEN = "男";
        private const string WOMEN = "女";

        private SelectedGender selectGender = SelectedGender.ALL;

        private void OnRadioAllChecked(object sender, RoutedEventArgs e)
        {
            selectGender = SelectedGender.ALL;
            collectionView?.Refresh();
        }

        private void OnRadioMenChecked(object sender, RoutedEventArgs e)
        {
            selectGender = SelectedGender.Men;
            collectionView?.Refresh();
        }

        private void OnRadioWomenChecked(object sender, RoutedEventArgs e)
        {
            selectGender = SelectedGender.Women;
            collectionView?.Refresh();
        }
    }
}

ICollectionViewのFilterプロパティ内で条件によって表示する行としない行を決めています。

ラジオボタンがチェックされる度に条件を入れ替え、ICollectionViewのRefreshメソッドを呼び出してビューを再作成します。

今回はDataGridの行を条件によってフィルタリングすることを確認しました。

関連記事

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

>> WPF DataGridの行を取得する

>> WPF DataGridの行を入れ替える

以上です。

コメント