web-dev-qa-db-ja.com

DataGridViewの自動並べ替えを実装するにはどうすればよいですか?

プログラムでDataGridViewに列を追加してから、リストにバインドしています。デフォルトでは、列のSortModeは自動です。しかし、アプリを実行するとき、ヘッダーをクリックしても何も起こりません。上/下矢印が表示されていません。 MSDNを読んでから、自動ソートについてはあまり語られていません。プログラムによる並べ替えについて詳しく説明します。だから、自動の方法は簡単なはずだと思います。 MSDNはさらに、「列ヘッダーが選択に使用されていない限り、列ヘッダーをクリックすると、DataGridViewがこの列で自動的に並べ替えられ、並べ替え順序を示すグリフが表示されます」と続けています。それは正確にはどういう意味ですか?並べ替えと競合するグリッドプロパティを設定できますか?何が足りないのですか?

AutoGenerateColumns = false;
AllowUserToAddRows = false;
AllowUserToDeleteRows = false;
AllowUserToResizeRows = false;
AllowUserToResizeColumns = false;
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
ReadOnly = true;
MultiSelect = false;
RowHeadersVisible = false;
SelectionMode = DataGridViewSelectionMode.FullRowSelect;
CellBorderStyle = DataGridViewCellBorderStyle.None;


    DataGridViewTextBoxColumn idColumn = new DataGridViewTextBoxColumn();
    idColumn.HeaderText = "ID";
    idColumn.DataPropertyName = "IDNumber";

    DataGridViewTextBoxColumn nameColumn = new DataGridViewTextBoxColumn();
    nameColumn.HeaderText = "Name";
    nameColumn.DataPropertyName = "Description";

    DataGridViewTextBoxColumn lastModifiedColumn = new DataGridViewTextBoxColumn();
    lastModifiedColumn.HeaderText = "Last Modified";
    lastModifiedColumn.DataPropertyName = "Date";

    Columns.Add(idColumn);
    Columns.Add(nameColumn);
    Columns.Add(lastModifiedColumn);

    List<IMyObject> bindingList = GetMyList();
    DataSource = bindingList;
15
bsh152s

BindingListView を使用してList <T>をDataGridViewsにバインドしますが、これはうまく機能しています。

オブジェクトのリストのビューを作成する非常に簡単な例を次に示します(C#で)。

List<Customer> customers = GetCustomers();
BindingListView<Customer> view = new BindingListView<Customer>(customers);
dataGridView1.DataSource = view;

DGVの並べ替えとデータバインディングの詳細については、 https://stackoverflow.com/a/17952576/116891 をご覧ください。

それほど重いものを追加したくない場合は、この実装を試すことができます SortableBindingList <T>更新あり )。

ベンチマークによると、どちらも箱から出してすぐに並べ替えることができ、BindingListViewはDataViewsよりもさらに高速です。

22
Chris Doggett

私が見つけた最良の解決策:

編集:投稿してから、この SortableBindingList(Of T) の実装が最良の解決策であることがわかりました。コンストラクターがとにかくキャストしていて機能するので、52行目をIEnumerableではなくICollectionに変更しました。

または、以下のソリューションにはカスタムクラスは必要ありません。

DataGridViewは、カスタムクラスを実装せずに並べ替えることができます。私のコードはVB.NETにありますが、変換する必要があることに注意してください。データは最初にgrid.Rowsに追加する必要があります。

For Each item In dataList
    grid.Rows.Add(item.Id, item.Name, item.DateProperty)
Next

次に、これらのイベントハンドラーを実装します。 2つ目は、日付の並べ替えが機能することを確認することです。グリッドに並べ替え可能な日付列がある場合にのみ必要です。

Private Sub grid_ColumnHeaderMouseClick(ByVal sender As Object, ByVal e As DataGridViewCellMouseEventArgs) Handles grid.ColumnHeaderMouseClick
    Dim col = grid.Columns(e.ColumnIndex)
    Dim dir As System.ComponentModel.ListSortDirection

    Select Case col.HeaderCell.SortGlyphDirection
        Case SortOrder.None, SortOrder.Ascending
            dir = System.ComponentModel.ListSortDirection.Ascending
        Case Else
            dir = System.ComponentModel.ListSortDirection.Descending
    End Select

    grid.Sort(col, dir)
End Sub

Private Sub grid_SortCompare(ByVal sender As Object, ByVal e As DataGridViewSortCompareEventArgs) Handles grid.SortCompare
    'This event occurs only when the DataSource property is not set and the VirtualMode property value is false.

    If e.Column.Name = "DateProperty" Then
        e.SortResult = Date.Compare(CType(e.CellValue1, Date), CType(e.CellValue2, Date))

        e.Handled = True
    End If

End Sub

注意すべき重要な点は、バインディングがないため、行に追加したプロパティのみが結果のオブジェクトの一部であるということです。オブジェクト全体を維持するには、すべてのプロパティに列を追加し、表示されるべきでない列にVisible = False列を設定する必要があります。

2
mbomb007

私は答えを見つけたと思います。私のデータソースはIList<T>を実装しています。どうやらそれはIBindingList<T>を実装する必要があります。残念ながら、これをテストすることはできません。

1
Michael J