【C# WPF DataGrid】ソートをオリジナルで実装

本記事では、C# WPFアプリケーションのDataGridのソートをオリジナルで実装する方法を書きます。

WPF DataGridは、ヘッダーをクリックすると、デフォルトでソートする機能があります。

しかし、

  • ソート状態を記憶したい
  • 独自のソートを実装したい

場合は、DataGridのソートをオリジナルで行う必要があります。

開発環境
  • Windows10
  • Microsoft Visual Studio Community2022
  • .NET 6
  • WPF アプリ
目次

DataGridのソートをオリジナルでやるために

.NETのDataGridのソースコードを確認してみます。

あわせて読みたい

確認したところ、7107行目以降が参考になりそうです。

        public event DataGridSortingEventHandler Sorting;
 
        /// <summary>
        /// Protected method which raises the sorting event and does default sort
        /// </summary>
        /// <param name="eventArgs"></param>
        protected virtual void OnSorting(DataGridSortingEventArgs eventArgs)
        {
            eventArgs.Handled = false;
            if (Sorting != null)
            {
                Sorting(this, eventArgs);
            }
 
            if (!eventArgs.Handled)
            {
                DefaultSort(
                    eventArgs.Column,
                    /* clearExistinSortDescriptions */
                    (Keyboard.Modifiers & ModifierKeys.Shift) != ModifierKeys.Shift);
            }
        }
https://source.dot.net/#PresentationFramework/System/Windows/Controls/DataGrid.cs,0a7919e43781659b

以下を実装すれば、オリジナルのソートができそうです。

  • Sorting にイベントを設定する
  • 設定したイベント内でeventArgs.Handled をtrueにする
  • 設定したイベント内でソート処理を実装する

DataGridのソートをオリジナルで実装

DataGridの自力ソートをオリジナルで実装してみます。以下記事のコードをオリジナル実装に変更します。

画面、動きは変わりません。C# .NETのソートを使用せず、オリジナルのコードでソートを実行します。

Xamlは以下のようになります。

MainWindow.xaml
<Window x:Class="DataGridProject.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:DataGridProject"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="500">
    <Grid x:Name="Grid_FruitsList">
        <Grid.Resources>
            <FrameworkElement x:Key="proxyElement" />
        </Grid.Resources>
        <ContentControl Visibility="Collapsed" Content="{StaticResource proxyElement}" />
        <DataGrid Margin="28,29,250,30"
                  AutoGenerateColumns = "False"
                  IsReadOnly="True" 
                  SelectionMode="Single"
                  RowHeaderWidth="0"
                  ItemsSource="{Binding Path=_friutsModelList}"
                  Sorting="DataGrid_Sorting" >
            <!-- 選択時に_isSelectedの値変更 -->
            <DataGrid.RowStyle>
                <Style TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">
                    <Setter Property="IsSelected" Value="{Binding _isSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                </Style>
            </DataGrid.RowStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Width="100" Binding="{Binding _name}">
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="Content" Value="{Binding Path=DataContext._nameHeader, Source={StaticResource proxyElement}}"/>
                            <Setter Property="Background" Value="Blue"/>
                            <Setter Property="Foreground" Value="White"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
                <DataGridTextColumn Width="50" Binding="{Binding _color}">
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="Content" Value="{Binding Path=DataContext._colorHeader, Source={StaticResource proxyElement}}"/>
                            <Setter Property="Background" Value="Blue"/>
                            <Setter Property="Foreground" Value="White"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
                <DataGridTextColumn Width="50" Binding="{Binding _price}">
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="Content" Value="{Binding Path=DataContext._priceHeader, Source={StaticResource proxyElement}}"/>
                            <Setter Property="Background" Value="Blue"/>
                            <Setter Property="Foreground" Value="White"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
        <GroupBox Margin="273,33,30,55" Header="選択中"/>
        <TextBlock HorizontalAlignment="Left" Margin="280,56,0,0" TextWrapping="Wrap" Text="名前 : " VerticalAlignment="Top" RenderTransformOrigin="0,-0.937"/>
        <TextBox x:Name="TextBox_Name" HorizontalAlignment="Left" Margin="325,56,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
        <TextBlock HorizontalAlignment="Left" Margin="280,89,0,0" TextWrapping="Wrap" Text="色 : " VerticalAlignment="Top" RenderTransformOrigin="0.603,2.195"/>
        <TextBox x:Name="TextBox_Color" HorizontalAlignment="Left" Margin="325,89,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
        <TextBlock HorizontalAlignment="Left" Margin="280,124,0,0" TextWrapping="Wrap" Text="価格 : " VerticalAlignment="Top"/>
        <TextBox x:Name="TextBox_Price" HorizontalAlignment="Left" Margin="325,122,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Window>

DataGridタグのSortingプロパティにイベントハンドラを設定します。

MainWindow.xaml.cs のイベントハンドラは以下のようになります。

        /// <summary>
        /// ヘッダーがクリックされたとき呼び出し
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DataGrid_Sorting(object sender, DataGridSortingEventArgs e)
        {
            e.Handled = true;

            string sortMemberPath = e.Column.SortMemberPath;

            dataGridSortDirector.Sort(sortMemberPath);
        }
  • e.Handledをtrueにし、.NETのソートを無効にします。
  • e.Column.SortMemberPathでクリックしたヘッダーの列のプロパティ名を取得します。
  • dataGridSortDirector.Sort でソート実行します。

プロジェクト一覧は↓から取得できます。ソート実行処理は長くなったので、説明は割愛します。また、行選択したときの処理は無効になっています。

GitHub
GitHub - HomeProgrammer81/DataGridProject at main_SortOriginal Contribute to HomeProgrammer81/DataGridProject development by creating an account on GitHub.

まとめ

記事では、C# WPFアプリケーションのDataGridのソートをオリジナルで実装する方法を書きました。

WPF のDataGridでデフォルトのソート機能を使用したくない場合はあると思います。そのときは、こちらの記事を参考にしてみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次