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

DataGridViewの行が自動的に並び替えられるようにする

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

DataGridViewColumn.SortModeプロパティがDataGridViewColumnSortMode.Automaticの時(DataGridViewTextBoxColumnではデフォルト)は、ユーザーが列をクリックすると、その列の内容でデータが並び替えられます。DataGridViewのDataSourceプロパティに並び替えが可能なデータソースが設定されており、仮想モードでない場合は、ユーザーが並び替えを行った後に新しい行を追加したり、セルの値を変更しても、その都度自動的に並び替えられます(詳細は、下記補足)。

プログラムで並び替えを行うには、DataGridView.Sortメソッドを使用します。Sortメソッドで並び替えられた後も、SortModeプロパティがAutomaticやProgrammaticであれば、ユーザーが列をクリックして並び替えたのと同じように、自動的に並び替えられます(詳細は、下記補足)。

補足:MSDN「DataGridViewRowCollection.Add メソッド」には、
「新しい行の追加時にコントロール内の行が自動的に並べ替えられることはありません。...また、CellValueChanged イベント ハンドラで System.Windows.Forms.DataGridView.Sort メソッドを呼び出すことにより、セルがユーザーによって変更されたときに行を並べ替えることもできます。」
とあり、DataGridViewに新しい行が追加されたり、セルの値が変更されたとしても、自動的に並び替えられることはないということになっています。しかし、DataGridViewのDataSourceプロパティが設定されており、仮想モードでない場合は、自動的に並び替えられるようです。これは、DataGridViewに自動的に並び替える機能はないが、データソースが自動的に並び替えられたということだと思われます。

プログラムで並び替えを行う例を紹介します。以下に示す例では、Button1をクリックすることにより、現在のセルの列で並び替えを行います。現在並び替えが行われている列とこれから並び替えを行う列が同じ場合は、昇順と降順をトグルで入れ替えて、それ以外では昇順で並び替えを行います。

VB.NET
コードを隠すコードを選択
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    '自動的に並び替えられるようにする
    Dim c As DataGridViewColumn
    For Each c In DataGridView1.Columns
        c.SortMode = DataGridViewColumnSortMode.Automatic
    Next c
End Sub

'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button1.Click
    If DataGridView1.CurrentCell Is Nothing Then
        Return
    End If

    '並び替える列を決める
    Dim sortColumn As DataGridViewColumn = _
        DataGridView1.CurrentCell.OwningColumn

    '並び替えの方向(昇順か降順か)を決める
    Dim sortDirection As System.ComponentModel.ListSortDirection = _
        System.ComponentModel.ListSortDirection.Ascending
    If Not (DataGridView1.SortedColumn Is Nothing) AndAlso _
            DataGridView1.SortedColumn.Equals(sortColumn) Then
        sortDirection = IIf(DataGridView1.SortOrder = SortOrder.Ascending, _
            System.ComponentModel.ListSortDirection.Descending, _
            System.ComponentModel.ListSortDirection.Ascending)
    End If

    '並び替えを行う
    DataGridView1.Sort(sortColumn, sortDirection)
End Sub
C#
コードを隠すコードを選択
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //自動的に並び替えられるようにする
    foreach (DataGridViewColumn c in DataGridView1.Columns)
        c.SortMode = DataGridViewColumnSortMode.Automatic;
}

//Button1のClickイベントハンドラ
private void Button1_Click(object sender, EventArgs e)
{
    if (DataGridView1.CurrentCell == null)
        return;

    //並び替える列を決める
    DataGridViewColumn sortColumn = DataGridView1.CurrentCell.OwningColumn;

    //並び替えの方向(昇順か降順か)を決める
    ListSortDirection sortDirection = ListSortDirection.Ascending;
    if (DataGridView1.SortedColumn != null &&
        DataGridView1.SortedColumn.Equals(sortColumn))
    {
        sortDirection =
            DataGridView1.SortOrder == SortOrder.Ascending ?
            ListSortDirection.Descending : ListSortDirection.Ascending;
    }

    //並び替えを行う
    DataGridView1.Sort(sortColumn, sortDirection);
}

自動的に並び替えられないときでも並び替えられるようにする

自動的に並び替えが行われない場合は、自分で並び替えを行います。さらに、SortModeプロパティがProgrammaticの場合は、並び替えグリフ(列ヘッダーの右側に表示される、昇順、降順のどちらで並び替えが行われているかを示す矢印)の表示も自分で行います。

列ヘッダーをクリックした時に並び替えを行うには、DataGridView.ColumnHeaderMouseClickイベントハンドラでSortメソッドを呼び出します。新しい行の追加後や、セルの編集後に並び替えが行われるようにするには、RowsAddedやCellValueChangedイベントハンドラでもSortメソッドを呼び出します。

また、並び替えグリフを表示するには、DataGridViewColumnHeaderCell.SortGlyphDirectionプロパティを設定します。

自動的に並び替えられないときでも、自動的に並び替えが行われるようにする例を以下に示します。列ヘッダーをクリックすると、その列を基準に、昇順、降順をトグルで変えて、並び替えが行われます。

VB.NET
コードを隠すコードを選択
'ColumnHeaderMouseClickイベントハンドラ
Private Sub DataGridView1_ColumnHeaderMouseClick(ByVal sender As Object, _
        ByVal e As DataGridViewCellMouseEventArgs) _
        Handles DataGridView1.ColumnHeaderMouseClick
    Dim clickedColumn As DataGridViewColumn = _
        DataGridView1.Columns(e.ColumnIndex)
    If clickedColumn.SortMode <> DataGridViewColumnSortMode.Automatic Then
        Me.SortRows(clickedColumn, True)
    End If
End Sub

'RowsAddedイベントハンドラ
Private Sub DataGridView1_RowsAdded(ByVal sender As Object, _
        ByVal e As DataGridViewRowsAddedEventArgs) _
        Handles DataGridView1.RowsAdded
    Me.SortRows(DataGridView1.SortedColumn, False)
End Sub

'CellValueChangedイベントハンドラ
Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, _
        ByVal e As DataGridViewCellEventArgs) _
        Handles DataGridView1.CellValueChanged
    If Not (DataGridView1.SortedColumn Is Nothing) AndAlso _
        e.ColumnIndex = DataGridView1.SortedColumn.Index Then
        Me.SortRows(DataGridView1.SortedColumn, False)
    End If
End Sub

''' <summary>
''' 指定された列を基準にして並び替えを行う
''' </summary>
''' <param name="sortColumn">基準にする列</param>
''' <param name="orderToggle">並び替えの方向をトグルで変更する</param>
Private Sub SortRows(ByVal sortColumn As DataGridViewColumn, _
        ByVal orderToggle As Boolean)
    If sortColumn Is Nothing Then
        Return
    End If

    '今までの並び替えグリフを消す
    If sortColumn.SortMode = DataGridViewColumnSortMode.Programmatic AndAlso _
        Not (DataGridView1.SortedColumn Is Nothing) AndAlso _
        Not DataGridView1.SortedColumn.Equals(sortColumn) Then
        DataGridView1.SortedColumn.HeaderCell.SortGlyphDirection = _
            SortOrder.None
    End If

    '並び替えの方向(昇順か降順か)を決める
    Dim sortDirection As System.ComponentModel.ListSortDirection
    If orderToggle Then
        sortDirection = IIf(DataGridView1.SortOrder = SortOrder.Descending, _
            System.ComponentModel.ListSortDirection.Ascending, _
            System.ComponentModel.ListSortDirection.Descending)
    Else
        sortDirection = IIf(DataGridView1.SortOrder = SortOrder.Descending, _
            System.ComponentModel.ListSortDirection.Descending, _
            System.ComponentModel.ListSortDirection.Ascending)
    End If
    Dim sOrder As SortOrder = _
        IIf(sortDirection = System.ComponentModel.ListSortDirection.Ascending, _
            SortOrder.Ascending, SortOrder.Descending)

    '並び替えを行う
    DataGridView1.Sort(sortColumn, sortDirection)

    If sortColumn.SortMode = DataGridViewColumnSortMode.Programmatic Then
        '並び替えグリフを変更
        sortColumn.HeaderCell.SortGlyphDirection = sOrder
    End If
End Sub
C#
コードを隠すコードを選択
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //イベントハンドラの追加
    DataGridView1.RowsAdded += new DataGridViewRowsAddedEventHandler(
        DataGridView1_RowsAdded);
    DataGridView1.CellValueChanged += new DataGridViewCellEventHandler(
        DataGridView1_CellValueChanged);
    DataGridView1.ColumnHeaderMouseClick += new DataGridViewCellMouseEventHandler(
        DataGridView1_ColumnHeaderMouseClick);
}

//ColumnHeaderMouseClickイベントハンドラ
private void DataGridView1_ColumnHeaderMouseClick(object sender,
    DataGridViewCellMouseEventArgs e)
{
    DataGridViewColumn clickedColumn = DataGridView1.Columns[e.ColumnIndex];
    if (clickedColumn.SortMode != DataGridViewColumnSortMode.Automatic)
        this.SortRows(clickedColumn, true);
}

//RowsAddedイベントハンドラ
private void DataGridView1_RowsAdded(object sender,
    DataGridViewRowsAddedEventArgs e)
{
    this.SortRows(DataGridView1.SortedColumn, false);
}

//CellValueChangedイベントハンドラ
private void DataGridView1_CellValueChanged(object sender,
    DataGridViewCellEventArgs e)
{
    if (DataGridView1.SortedColumn != null &&
        e.ColumnIndex == DataGridView1.SortedColumn.Index)
        this.SortRows(DataGridView1.SortedColumn, false);
}

/// <summary>
/// 指定された列を基準にして並び替えを行う
/// </summary>
/// <param name="sortColumn">基準にする列</param>
/// <param name="orderToggle">並び替えの方向をトグルで変更する</param>
private void SortRows(DataGridViewColumn sortColumn, bool orderToggle)
{
    if (sortColumn == null)
        return;

    //今までの並び替えグリフを消す
    if (sortColumn.SortMode == DataGridViewColumnSortMode.Programmatic &&
        DataGridView1.SortedColumn != null &&
        !DataGridView1.SortedColumn.Equals(sortColumn))
    {
        DataGridView1.SortedColumn.HeaderCell.SortGlyphDirection =
            SortOrder.None;
    }

    //並び替えの方向(昇順か降順か)を決める
    ListSortDirection sortDirection;
    if (orderToggle)
    {
        sortDirection =
            DataGridView1.SortOrder == SortOrder.Descending ?
            ListSortDirection.Ascending : ListSortDirection.Descending;
    }
    else
    {
        sortDirection =
            DataGridView1.SortOrder == SortOrder.Descending ?
            ListSortDirection.Descending : ListSortDirection.Ascending;
    }
    SortOrder sortOrder =
        sortDirection == ListSortDirection.Ascending ?
        SortOrder.Ascending : SortOrder.Descending;

    //並び替えを行う
    DataGridView1.Sort(sortColumn, sortDirection);

    if (sortColumn.SortMode == DataGridViewColumnSortMode.Programmatic)
    {
        //並び替えグリフを変更
        sortColumn.HeaderCell.SortGlyphDirection = sortOrder;
    }
}

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

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