WPFのDataGridは、ヘッダーをクリックするとその列でソートしてくれる。
(ちなみにソート後のSelectedIndexプロパティは並び変わった後のIndexなので、ItemsSourceへセットしたデータ配列のIndexには使えないので注意)
この並び変えを自分でカスタマイズしたい場合、DataGridのSortingイベントを利用する。
以下の例では、 大量にあるデータのうち先頭の数件だけをDataGridに表示しているが、ソート順に応じてDataGridのItemsSourceを作り変えている。
XAML
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="400">
<Grid Margin="10" HorizontalAlignment="Stretch">
<DataGrid x:Name="CtrlDataGrid" Sorting="CrtlDataGrid_Sorting">
</DataGrid>
</Grid>
</Window>
DataGridのSortingイベントを追加しメソッドを指定する。
ソース
public partial class MainWindow : Window
{
public class TestItem {
public int Column1 { get; set; }
public int Column2 { get; set; }
public int Column3 { get; set; }
public int Column4 { get; set; }
};
List<TestItem> TestList = new List<TestItem>();
public MainWindow()
{
for (int i = 0; i < 1000; ++i)
{
var item = new TestItem();
item.Column1 = i;
item.Column2 = i % 10;
item.Column3 = i % 7;
item.Column4 = i % 13;
TestList.Add(item);
}
InitializeComponent();
CtrlDataGrid.ItemsSource = TestList.OrderBy(c => c.Column1).Take(13);
}
private void CrtlDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
var i = CtrlDataGrid.SelectedIndex;
MessageBox.Show(string.Format("{0}", i));
}
private void CrtlDataGrid_Sorting(object sender, DataGridSortingEventArgs e)
{
e.Handled = true;
var sortDir = e.Column.SortDirection;
if (ListSortDirection.Ascending != sortDir)
sortDir = ListSortDirection.Ascending;
else
sortDir = ListSortDirection.Descending;
if (ListSortDirection.Ascending == sortDir)
{
if ("Column1" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderBy(c => c.Column1).Take(13);
if ("Column2" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderBy(c => c.Column2).Take(13);
if ("Column3" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderBy(c => c.Column3).Take(13);
if ("Column4" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderBy(c => c.Column4).Take(13);
}
else
{
if ("Column1" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderByDescending(c => c.Column1).Take(13);
if ("Column2" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderByDescending(c => c.Column2).Take(13);
if ("Column3" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderByDescending(c => c.Column3).Take(13);
if ("Column4" == e.Column.SortMemberPath)
CtrlDataGrid.ItemsSource = TestList.OrderByDescending(c => c.Column4).Take(13);
}
foreach (var column in CtrlDataGrid.Columns)
{
if (column.SortMemberPath == e.Column.SortMemberPath)
{
column.SortDirection = sortDir;
}
}
}
}
既存のソート処理をしない (37行目)
DataGridSortingEventArgsのHandlerにtrueをセットする事で既存のソート処理が行われなくなる
新たなソート順を決める (41~44行目)
DataGridSortingEventArgsのColumn.SortDirectionに現在のソート順が入っている
- null ・・・ ソートされていない
- Ascending ・・・ 昇順(ヘッダーに▲が表示されている状態)
- Descending ・・・ 降順(ヘッダーに▼が表示されている状態)
現在のソート順を元に新たなソート順を決めている
データを作り直す (46~67行目)
DataGridSortingEventArgsのColumn.SortMemberPathにソート対象のメンバーが入っているのでそれに従ってItemsSourceを作り直している
ヘッダーのソート順を正しくセットする (69~75行目)
通常はDataGridSortingEventArgsのColumn.SortDirectionへ新たな値をセットすれば良さそうだがItemsSourceを作り直している為かそれではうまくいかない
DataGridのColumnsから該当のカラムを見つけて新たなSortDirectionをセットする

コメント
コメントを投稿