这个问题与这两个(this和this)密切相关,但我认为他们没有给出令人满意的答案。
我有一个
DataGridView
(即一个表),其中包含不同数据类型的几列(DataGridViewTextBoxColumn
):字符串,整数和浮点数。当我单击它们各自的标题时,应根据它们的类型对每个标题进行排序:按字母顺序排列的字符串和按数字排列的数值。简单地说,我有以下代码:
private System.Windows.Forms.DataGridView grid;
private System.Windows.Forms.DataGridViewTextBoxColumn stringColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn doubleColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn intColumn;
stringColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
doubleColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
intColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
stringColumn,
doubleColumn,
intColumn});
然而,由于默认表示是
string
,数值也会按字母顺序排序,例如:
1, 11, 2, 3, 42, 5
显然,作为解决这个问题的简单方法,根据一些线程(例如here和here),以下应该可以立即解决问题:
doubleColumn.ValueType = typeof(double);
intColumn.ValueType = typeof(int);
但是,这个解决方案在我的项目中根本不起作用:值仍然按字母顺序排序。所以问题是:为什么不呢?在调试器中,我可以看到值类型实际上更改为(在
double
情况下)System.Double
,所以至少发生了一些事情。但是,如果不编写我自己的排序器,我如何才能确保它确实对其进行了相应的排序?
你可以处理事件
SortCompare
来改变排序的方式,像这样:
private void dataGridView1_SortCompare(object sender, DataGridViewSortCompareEventArgs e) {
//Suppose your interested column has index 1
if (e.Column.Index == 1){
e.SortResult = int.Parse(e.CellValue1.ToString()).CompareTo(int.Parse(e.CellValue2.ToString()));
e.Handled = true;//pass by the default sorting
}
}
注意:上面的代码假设您的单元格值可以转换为int。
你说你的
DataGridView
没有分配DataSource
,这意味着你手动Add
行,所以我认为你应该为你的细胞使用numeric
值而不是string
。这将使排序工作如你所愿。
如果您使用的是
DataTable
,那么您必须在DataType
上设置DataColumn
。在 ValueType
上设置 DataGridViewTextBoxColumn
将无济于事。
创建时可以设置:
table.Columns.Add("Number", typeof(int));
将列从
string
更改为 int32
可能会有所帮助:
for (int i = 0; i < tableDataGridView.Rows.Count; i++) {
DateTime dt = Convert.ToDateTime(tableDataGridView.Rows[i].Cells[9].Value.ToString());
DateTime dtnow = DateTime.Now;
TimeSpan ts = dtnow.Subtract(dt);
tableDataGridView.Rows[i].Cells[1].Value = Convert.ToInt32( ts.Days.ToString());
}
tableDataGridView.Sort(tableDataGridView.Columns[1], ListSortDirection.Descending);
对我来说,它有效。我希望它会有所帮助。
将您的列 ValueType 设置为 typeof(int) 将起作用,请记住确保将整数放入该列。如果您的其余数据包含字符串,则很容易忘记将您的数字从字符串转换为整数。
https://www.youtube.com/watch?v=kKeTRPSLxX8 看这个视频,很有帮助
复制该视频中的代码:
Private Sub dgvDailySales_SortCompare(sender As Object, e As DataGridViewSortCompareEventArgs) Handles dgvDailySales.SortCompare
Try
Dim dval1, dval2 As Double
If Not Double.TryParse(e.CellValue1.ToString, dval1) Then Return
If Not Double.TryParse(e.CellValue2.ToString, dval2) Then Return
If dval1 = dval2 Then
e.SortResult = 0
ElseIf dval2 > dval1 Then
e.SortResult = -1
ElseIf dval1 > dval2 Then
e.SortResult = 1
End If
e.Handled = True
Catch ex As Exception
MsgBox(ex.Message, vbCritical)
End Try
End Sub
我使用此代码在列包含数字的位置进行数字排序,即使有字母值也能正常工作。
Private Sub grid_SortCompare(ByVal sender As Object, ByVal e As DataGridViewSortCompareEventArgs) Handles grid.SortCompare
If e.Column.Index = grid.Columns("colNrFct").Index Then
If Not isNumeric(e.CellValue1) And Not isNumeric(e.CellValue2) Then
e.SortResult = 0
ElseIf Not isNumeric(e.CellValue1) And isNumeric(e.CellValue2) Then
e.SortResult = -1
ElseIf isNumeric(e.CellValue1) And Not isNumeric(e.CellValue2) Then
e.SortResult = 1
ElseIf Double.Parse(e.CellValue1.ToString()) > Double.Parse(e.CellValue2.ToString()) Then
e.SortResult = 1
ElseIf Double.Parse(e.CellValue1.ToString()) < Double.Parse(e.CellValue2.ToString()) Then
e.SortResult = -1
Else
e.SortResult = 0
End If
e.Handled = True
End If
End Sub