【C#】DataGridViewの列ヘッダーでソートする ~標準ソートとカスタムソート~

広告

一覧表示で地味に重要なのが「列ヘッダーをクリックすると並び替わる」機能です。DataGridViewは何も書かなくてもある程度自動でソートしてくれますが、DataTableと連携している場合や、独自の並び順にしたい場合はひと手間必要になります。本記事では標準のソート機能と、IComparerを使ったカスタムソートを紹介します。

1. 標準のソート機能を有効にする

DataGridViewをDataSet/DataTableにバインドしている場合、実は特別な設定をしなくても列ヘッダーをクリックするだけで自動的に並び替わります。これはDataTableのビュー機能(DefaultView.Sort)を裏で使っているためです。

明示的にソート可否をコントロールしたい場合は、列ごとにSortModeを設定します。

// 特定の列だけソート不可にする
dataGridView1.Columns["Memo"].SortMode = DataGridViewColumnSortMode.NotSortable;

// プログラムから昇順/降順を指定してソートする
dataGridView1.Sort(dataGridView1.Columns["Name"], ListSortDirection.Ascending);

DataSourceを使わず、行を手動でRows.Addしているだけの場合は自動ソートが効かないことがあるので、その場合は次のカスタムソートを使います。

2. IComparerでカスタムソートを実装する

「数値混じりの文字列を自然順(1, 2, 10の順)で並べたい」「複数列を優先順位付きでソートしたい」といった要望には、IComparerを実装してソートロジックを自作します。

public class NaturalStringComparer : System.Collections.IComparer
{
    private readonly int _columnIndex;

    public NaturalStringComparer(int columnIndex)
    {
        _columnIndex = columnIndex;
    }

    public int Compare(object x, object y)
    {
        var rowX = (DataGridViewRow)x;
        var rowY = (DataGridViewRow)y;

        string valX = rowX.Cells[_columnIndex].Value?.ToString() ?? "";
        string valY = rowY.Cells[_columnIndex].Value?.ToString() ?? "";

        // 数値として解釈できればそちらを優先
        if (int.TryParse(valX, out int numX) && int.TryParse(valY, out int numY))
        {
            return numX.CompareTo(numY);
        }

        return string.Compare(valX, valY, StringComparison.Ordinal);
    }
}

呼び出し側では、DataSourceを使わない場合に限りSort(IComparer)が使えます(DataSourceバインディング中は使えないので注意)。

private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    dataGridView1.Sort(new NaturalStringComparer(e.ColumnIndex));
}

3. ソート状態をヘッダーに表示する(▲▼マーク)

ユーザーが「今どの列で、昇順/降順どちらでソートされているか」を視覚的に分かるようにするには、DataGridView.SortGlyphDirectionを使います。

dataGridView1.Columns["Name"].HeaderCell.SortGlyphDirection = SortOrder.Ascending;

DataSourceバインディング時の標準ソートでは自動でこの矢印が表示されますが、カスタムソートを自作した場合は自分でこのプロパティを更新する必要があります。

まとめ

  • DataSet/DataTableバインディング時は、特別な実装なしでヘッダークリックによるソートが効く
  • 独自の並び順やDataSourceなしの一覧ではIComparerを実装してカスタムソート
  • カスタムソート時はソート矢印(SortGlyphDirection)の更新も忘れずに

次回は、入力値のバリデーション(CellValidatingイベント)を扱います。

訪問数 3 回, 今日の訪問数 7回

広告

WindowsFormアプリ

Posted by hidepon