【问题标题】:How do I implement automatic sorting of DataGridView?如何实现DataGridView的自动排序?
【发布时间】:2011-04-15 19:29:39
【问题描述】:

我以编程方式将列添加到 DataGridView,然后绑定到列表。默认情况下,列的 SortMode 为 Automatic。但是当我运行我的应用程序时,单击标题没有任何作用。向上/向下箭头未显示。从阅读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;

【问题讨论】:

  • 他们所说的字形是列标题中的向上/向下箭头。尝试注释掉所有非默认网格设置,看看它们是否与排序冲突。
  • 我也有同样的问题。该文档让人认为它应该自动工作。
  • 我也是! :) 坦率地说,IMO 甚至没有基本的基于 IComparable 的开箱即用排序的网格是不完整的。
  • 此处记录了另一种解决方案:stackoverflow.com/a/28520948/3317709.

标签: c# sorting datagridview


【解决方案1】:

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

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

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

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

如果您不想添加那么重的东西,可以尝试SortableBindingList<T> (with updates) 的这种实现。

根据它们的基准,两者都可以让您立即进行排序,而且 BindingListView 甚至比 DataView 更快。

【讨论】:

  • 我同意,就像一个魅力 :) 虽然我主要使用来自 Linq2SQL 的 BindingLists。
  • 谢谢克里斯。我想我明白现在发生了什么。我没有得到 DataViewGrid 控件想要重新排序存储的数据。我需要一个解决方案,在不更改底层数据源的情况下更改控件中的顺序。
  • @leppie: BindingList 不能为我解决这个问题。
  • @Dan:再读一遍。您不能只使用BindingList&lt;T&gt;,您需要一个可排序的,就像答案中的那个。
  • @Dan:Linq2SQL 返回的列表是SortableBindingList&lt;T&gt;。然而,这种类型是internal,所以它返回为BindingList&lt;T&gt; 类型。该实例仍然是可排序的。
【解决方案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 设置为任何不应显示的列。

【讨论】:

    【解决方案3】:

    我想我找到了答案。我的数据源实现IList&lt;T&gt;。显然它需要实现IBindingList&lt;T&gt;。不幸的是,我无法对此进行测试。

    【讨论】:

    • 你说得对,它确实需要实现BindingList。请参阅我对一些开源实现的回答。
    • 我使用未实现 IBindingList 的数据源手动实现了 DataGridView 排序,但经过大量努力后,我永远无法显示排序字形。我很确定排序字形的代码要么有问题,要么有不必要的限制。它们甚至无法手动打开和设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 2015-05-12
    相关资源
    最近更新 更多