本記事では、C# WPFアプリケーションのDataGridのソートをオリジナルで実装する方法を書きます。
WPF DataGridは、ヘッダーをクリックすると、デフォルトでソートする機能があります。
しかし、
- ソート状態を記憶したい
- 独自のソートを実装したい
場合は、DataGridのソートをオリジナルで行う必要があります。
開発環境
- Windows10
- Microsoft Visual Studio Community2022
- .NET 6
- WPF アプリ
目次
DataGridのソートをオリジナルでやるために
.NETのDataGridのソースコードを確認してみます。
確認したところ、7107行目以降が参考になりそうです。
https://source.dot.net/#PresentationFramework/System/Windows/Controls/DataGrid.cs,0a7919e43781659bpublic 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); } }
以下を実装すれば、オリジナルのソートができそうです。
- Sorting にイベントを設定する
- 設定したイベント内でeventArgs.Handled をtrueにする
- 設定したイベント内でソート処理を実装する
DataGridのソートをオリジナルで実装
DataGridの自力ソートをオリジナルで実装してみます。以下記事のコードをオリジナル実装に変更します。
【C# WPF DataGrid】ヘッダー背景変更でソート後の三角( 矢印▲▼ ) を表示
C# WPFアプリケーションで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 でソート実行します。
プロジェクト一覧は↓から取得できます。ソート実行処理は長くなったので、説明は割愛します。また、行選択したときの処理は無効になっています。
まとめ
記事では、C# WPFアプリケーションのDataGridのソートをオリジナルで実装する方法を書きました。
WPF のDataGridでデフォルトのソート機能を使用したくない場合はあると思います。そのときは、こちらの記事を参考にしてみてください。
コメント