C#:自定义DataGridView

我需要使用自然排序(在资源管理器中)对DataGridView进行排序,以便数字和文本(在同一列中)自然排序,而不是按字母顺序排序(以便“位置3”位于“位置20”之前,等等)。 我有一个DataGridView,我将DataView设置为DataSource。 DataView包含一个DataTable,它是使用数据库中的某些值创建的。 列类型是字符串。 我有一个IComparer,它做了应有的事情,但我无法弄清楚如何使用它,因为我无法找到如何进行排序。 DataGridView.SortCompare事件是完美的 ,因为它是数据绑定的,所以不起作用。 DataView.Sort只接受具有列名和排序顺序的字符串。

很烦人。 试图在StackOverflow上阅读相关问题,并搜索谷歌的很多和很多,但我真的找不到这个。 只有我真正找到的东西是使用dataview的Sort(字符串)方法,因为它按字母顺序排序。

有没有人知道如何做到这一点没有太多麻烦? 它应该是别人而不是我这个? 我真的不想重新实现整个datagridview或dataview类,只是为了获得自定义排序…

更新 :如果有人想知道,我仍然在寻找这个问题的好答案。 虽然与此同时,我最终创建了自己的简单表类,然后手动将其提供给datagridview。 覆盖SortCompare方法。 有点烦人,但不是太难,因为我只需要显示值(没有编辑或任何东西),因此可以将所有内容转换为字符串。

看看这个MSDN页面和这篇博客文章 。 原则上,您需要在GridView上配置数据源(无论是ObjectDataSource还是SqlDataSource)的排序。

据我所知,DataView类除了简单的升序/降序排序外不支持任何其他内容。 如果没有看到加载和绑定数据的代码,很难做出具体的推荐,但你可以:

  1. 将数据加载到List而不是DataTable中,调用Sort方法传递比较方法,然后绑定到该列表。
  2. 在aspx代码中创建一个ObjectDataSource,直接从类中获取数据,并将ObjectDataSource配置为使用IComparer。

这段代码应该有效。 它类似于ListView的ListViewItemSorter。 使用IComparer。

使用:

private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { MyDataGridHelper.DataGridSort(dgv, e.ColumnIndex); } 

MyDataGridHelper.cs:

 public class MyDataGridHelper { public static void DataGridSort(DataGridView dgv, int column) { DataGridViewCustomSorter dgvSorter = null; if (dgv.Tag == null || !(dgv.Tag is IComparer)) { dgvSorter = new DataGridViewCustomSorter(dgv); dgv.Tag = dgvSorter; } else { dgvSorter = (DataGridViewCustomSorter)dgv.Tag; } dgvSorter.SortColumn = column; dgv.Sort(dgvSorter); } private class DataGridViewCustomSorter : IComparer { private int ColumnIndex; private SortOrder OrderOfSort; private DataGridView myDataGridView; private TypeCode mySortTypeCode; public DataGridViewCustomSorter(DataGridView dgv) { myDataGridView = dgv; mySortTypeCode = Type.GetTypeCode(Type.GetType("System.String")); ColumnIndex = 0; OrderOfSort = SortOrder.None; } public int Compare(object x, object y) { int result; DataGridViewRow dgvX, dgvY; dgvX = (DataGridViewRow)x; dgvY = (DataGridViewRow)y; string sx = dgvX.Cells[ColumnIndex].Value.ToString(); string sy = dgvY.Cells[ColumnIndex].Value.ToString(); //null handling if (sx == String.Empty && sy == String.Empty) result = 0; else if (sx == String.Empty && sy != String.Empty) result = -1; else if (sx != String.Empty && sy == String.Empty) result = 1; else { switch (mySortTypeCode) { case TypeCode.Decimal: Decimal nx = Convert.ToDecimal(sx); Decimal ny = Convert.ToDecimal(sy); result = nx.CompareTo(ny); break; case TypeCode.DateTime: DateTime dx = Convert.ToDateTime(sx); DateTime dy = Convert.ToDateTime(sy); result = dx.CompareTo(dy); break; case TypeCode.String: result = (new CaseInsensitiveComparer()).Compare(sx, sy); break; default: result = (new CaseInsensitiveComparer()).Compare(sx, sy); break; } } if (OrderOfSort == SortOrder.Descending) result = (-result); return result; } public int SortColumn { set { if (ColumnIndex == value) { OrderOfSort = (OrderOfSort == SortOrder.Descending ? SortOrder.Ascending : SortOrder.Descending); } ColumnIndex = value; try { mySortTypeCode = Type.GetTypeCode(Type.GetType((myDataGridView.Columns[ColumnIndex]).Tag.ToString())); } catch { mySortTypeCode = TypeCode.String; } } get { return ColumnIndex; } } public SortOrder Order { set { OrderOfSort = value; } get { return OrderOfSort; } } } //end class DataGridViewCustomSorter } //end class MyDataGridHelper 

您可以创建2个隐藏列。 将文本部分分配给第一个隐藏列,将数字部分分配给第二个隐藏列。 现在按这些隐藏列排序(第一列的alpha排序和第二列的数字排序)。

通过这种方式,您可以保留原始列以用于显示目的,并具有2个用于排序的隐藏列。

这里有一些解决方案“ 使用SortCompare事件进行 自定义排序 ”和“ 使用IComparer接口进行自定义排序 ”:

http://msdn.microsoft.com/en-us/library/ms171608.aspx

您可以将排序逻辑移动到数据库查询中,并使其返回具有正确排序顺序的其他列。

然后(沿着@True C Sharp的回答)你可以有一个包含这个值的隐藏列,并按此而不是显示列进行排序。

这假定用于确定排序顺序的逻辑可以在SQL中执行。 如果用于确定排序顺序的算法很复杂,则这可能不起作用。