如何实现DataGridView的自动排序?

问题描述 投票:0回答:4

我以编程方式将列添加到 DataGridView,然后绑定到列表。默认情况下,列的排序模式为自动。但是当我运行我的应用程序时,单击标题没有任何反应。向上/向下箭头未显示。从看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;
c# sorting datagridview
4个回答
23
投票

我们使用 BindingListView 将 List 绑定到 DataGridView,它对我们来说效果很好。

这是一个创建对象列表视图的非常简单的示例(在 C# 中):

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

查看 https://stackoverflow.com/a/17952576/116891,了解有关 DGV 排序和数据绑定的更多详细信息。

如果您不想添加那么重的东西,您可以尝试实现SortableBindingList带有更新)。

两者都可以让您开箱即用地进行排序,根据基准测试,BindingListView 甚至比 DataView 更快。


2
投票

我找到的最佳解决方案:

编辑:自从发布以来,我发现

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

然后实现这些事件处理程序。第二个是确保日期排序有效。仅当您的网格具有可排序的日期列时,您才需要它:

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


1
投票

我想我找到了答案。我的数据源实现了

IList<T>
。显然它需要实施
IBindingList<T>
。不幸的是,我无法对此进行测试。


0
投票

我无话可说...... 存在覆盖默认 BindingList<>... 的解决方案,因为 BindingList 隐藏了一个受保护的属性,该属性是一个指示是否支持排序的标志:

msdn:

SupportsSortingCore 属性指示 BindingList 是否 支持使用ApplySortCore方法进行排序。

BindingList 类提供基本实现 排序,因此默认情况下 SupportsSortingCore 始终返回 false。为了 有关实现排序的更多信息,请参阅ApplySortCore 方法。

您可以拉伸和暴力破解数据网格视图的属性,如果您绑定到 BindingList<>,您将永远无法对其进行排序!

© www.soinside.com 2019 - 2024. All rights reserved.