DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DataGridViewの行の並び替えの方法を変更する

注意:DataGridViewコントロールは、.NET Framework 2.0で新しく追加されました。

ここでは、通常では並び替えのできない列を基準とした並び替えや、通常の並び替えとは違った方法での並び替え、複数列を比較しての並び替えなどといったように、並び替え方をカスタマイズする方法を紹介します。

並べ替え方を指定する方法は、幾つかあります。DataGridViewで並び替えを行う方法としては、SortメソッドでIComparerを指定して呼び出す方法や、SortCompareイベントを処理する方法があります。また、DataGridViewのDataSourceプロパティにデータソースが設定されている場合は、DataView.Sortプロパティなどにより、データソースを並び替えます。これらについて、以下に一つずつ紹介します。

DataGridView.Sortメソッドを使用する方法

この方法は、DataGridViewのDataSourceプロパティが設定されておらず、VirtualModeプロパティがFalseの場合に使用できます。

DataGridView.Sortメソッドを使用して並び替え方を変更するには、IComparerを使用します。IComparerにより並び替えを行う方法は、「配列やコレクション内の要素を並び替える」で説明しています。よってここでは詳しくは説明せず、サンプルだけを示します。

以下に紹介する例では、はじめにインデックスが0番目の列を比較し、もしその列が同じならば次の列で比較を行うことにより、並び替えをしています。

まずは、次のようなIComparerインターフェイスを実装したクラスを作成します。

VB.NET
コードを隠すコードを選択
'IComparerインターフェイスを実装した、並び替える方法を定義したクラス
Public Class CustomComparer
    Implements IComparer
    Private sOrder As Integer
    Private comparer As Comparer

    Public Sub New(ByVal order As SortOrder)
        Me.sOrder = IIf(order = SortOrder.Descending, -1, 1)
        Me.comparer = New Comparer( _
            System.Globalization.CultureInfo.CurrentCulture)
    End Sub

    '並び替え方を定義する
    Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
         Implements System.Collections.IComparer.Compare
        Dim result As Integer = 0

        Dim rowx As DataGridViewRow = CType(x, DataGridViewRow)
        Dim rowy As DataGridViewRow = CType(y, DataGridViewRow)

        'はじめの列のセルの値を比較し、同じならば次の列を比較する
        For i As Integer = 0 To rowx.Cells.Count - 1
            result = Me.comparer.Compare( _
                rowx.Cells(i).Value, rowy.Cells(i).Value)
            If result <> 0 Then
                Exit For
            End If
        Next i

        '結果を返す
        Return result * Me.sOrder
    End Function
End Class
C#
コードを隠すコードを選択
//IComparerインターフェイスを実装した、並び替える方法を定義したクラス
public class CustomComparer : IComparer
{
    private int sortOrder;
    private Comparer comparer;

    public CustomComparer(SortOrder order)
    {
        this.sortOrder = (order == SortOrder.Descending ? -1 : 1);
        this.comparer = new Comparer(
            System.Globalization.CultureInfo.CurrentCulture);
    }

    //並び替え方を定義する
    public int Compare(object x, object y)
    {
        int result = 0;

        DataGridViewRow rowx = (DataGridViewRow)x;
        DataGridViewRow rowy = (DataGridViewRow)y;

        //はじめの列のセルの値を比較し、同じならば次の列を比較する
        for (int i = 0; i < rowx.Cells.Count; i++)
        {
            result = this.comparer.Compare(
                rowx.Cells[i].Value, rowy.Cells[i].Value);
            if (result != 0)
                break;
        }

        //結果を返す
        return result * this.sortOrder;
    }
}

実際に並び替えを行うには、次のようなコードを書きます。ここでは、昇順で並び替えます。

VB.NET
コードを隠すコードを選択
'昇順で並び替えを行う
DataGridView1.Sort(New CustomComparer(SortOrder.Ascending))
C#
コードを隠すコードを選択
//昇順で並び替えを行う
DataGridView1.Sort(new CustomComparer(SortOrder.Ascending));

SortCompareイベントを使用する方法

この方法も、DataGridViewのDataSourceプロパティが設定されておらず、VirtualModeプロパティがFalseの場合に使用できます。

SortCompareイベントは、DataGridViewが並べ替えを行うために2つのセルの値を比較する時に発生します。このイベントは、DataGridViewColumn.SortModeプロパティがAutomaticの時にユーザーが列ヘッダーをクリックした時や、IComparerを使用せずにDataGridView.Sortメソッドを呼び出した場合にで並び替えを行った時に発生するため、これらにより並び替えが行われた時の並べ替え方を定義できます。

SortCompareイベントを使用する方法も、DataGridView.Sortメソッドを使用する方法を理解していれば、簡単です。SortCompareイベントハンドラで取得できるDataGridViewSortCompareEventArgsオブジェクトのCellValue1とCellValue2を比較し、CellValue1のほうが大きければ正の整数を、CellValue2のほうが大きければ負の整数を、両方同じならば0をSortResultプロパティに代入します。そして、HandledプロパティをTrueにします。

以下の例では、セルの値を文字列に変換した時の長さによって並び替えるようにしています。

VB.NET
コードを隠すコードを選択
'DataGridView1のSortCompareイベントハンドラ
Private Sub DataGridView1_SortCompare(ByVal sender As Object, _
        ByVal e As DataGridViewSortCompareEventArgs) _
        Handles DataGridView1.SortCompare
    '指定されたセルの値を文字列として取得する
    Dim str1 As String
    If e.CellValue1 Is Nothing Then
        str1 = ""
    Else
        str1 = e.CellValue1.ToString
    End If
    Dim str2 As String
    If e.CellValue2 Is Nothing Then
        str2 = ""
    Else
        str2 = e.CellValue2.ToString
    End If

    '結果を代入
    e.SortResult = str1.Length - str2.Length
    '処理したことを知らせる
    e.Handled = True
End Sub
C#
コードを隠すコードを選択
//DataGridView1のSortCompareイベントハンドラ
private void DataGridView1_SortCompare(object sender,
    DataGridViewSortCompareEventArgs e)
{
    //指定されたセルの値を文字列として取得する
    string str1 = (e.CellValue1 == null ? "" : e.CellValue1.ToString());
    string str2 = (e.CellValue2 == null ? "" : e.CellValue2.ToString());

    //結果を代入
    e.SortResult = str1.Length - str2.Length;
    //処理したことを知らせる
    e.Handled = true;
}

複数の列により並び替えを行う場合は、DataGridViewSortCompareEventArgsオブジェクトのRowIndex1とRowIndex2プロパティを使用します。この行インデックスからDataGridViewRowオブジェクトを取得して、比較を行います。

DataView.Sortプロパティを使用する方法

DataGridViewのDataSourceプロパティにデータソースが設定されている場合は、データソースを並び替えます。データソースの並び替えは、DataView.Sort プロパティBindingSource.Sort プロパティなどで行うことができます。ここでは、DataView.Sortプロパティを使用する方法を紹介します。

例えばColumn1列を昇順で並び替えるなら、Sortプロパティを"Column1 ASC"とします。降順であれば、ASCの代わりにDESCとします。Column1とColumn2の2つの列で並び替えるなら、"Column1, Column2 ASC"(または"Column1 ASC, Column2 ASC")のようにします。

以下の例では、DataGridView1にDataTableがバインドされている時、Column1とColumn2列で昇順に並び替えています。並び替えグリフの表示も、2つの列で行っています。

VB.NET
コードを隠すコードを選択
'DataGridView1にバインドされているDataTableを取得
Dim dt As DataTable = CType(DataGridView1.DataSource, DataTable)
'DataViewを取得
Dim dv As DataView = dt.DefaultView
'Column1とColumn2で昇順に並び替える
dv.Sort = "Column1, Column2 ASC"

'2つの列のヘッダーに並び替えグリフを表示する
DataGridView1.Columns("Column1").HeaderCell.SortGlyphDirection = _
    SortOrder.Ascending
DataGridView1.Columns("Column2").HeaderCell.SortGlyphDirection = _
    SortOrder.Ascending
C#
コードを隠すコードを選択
//DataGridView1にバインドされているDataTableを取得
DataTable dt = (DataTable)DataGridView1.DataSource;
//DataViewを取得
DataView dv = dt.DefaultView;
//Column1とColumn2で昇順に並び替える
dv.Sort = "Column1, Column2 ASC";

//2つの列のヘッダーに並び替えグリフを表示する
DataGridView1.Columns["Column1"].HeaderCell.SortGlyphDirection =
    SortOrder.Ascending;
DataGridView1.Columns["Column2"].HeaderCell.SortGlyphDirection =
    SortOrder.Ascending;

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。