Reputation: 3966
This question is closely related to these two (this and this) but I don't think they give a satisfying answer.
I have a DataGridView
(i.e. a table) with several columns (DataGridViewTextBoxColumn
) of different data types: string, integers and floats. When I click on their respective header, each should be sorted according to their type: string alphabetically and numerical values numerically. I have, simply put, the following code:
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});
However, since the default representation is string
, the numerical values also get sorted alphabetically, for example like this:
1, 11, 2, 3, 42, 5
Apparently, as an easy way of getting around this, according some threads (e.g. here and here), the following should work immediately solve the problem:
doubleColumn.ValueType = typeof(double);
intColumn.ValueType = typeof(int);
However, this solution simply doesn't work in my project: values are still sorted alphabetically. So the question is: why not? In the Debugger, I could see that the value type actually changed to (in the double
case) System.Double
, so something is happening at least. But how can I make sure that it actually sorts it accordingly, without writing my own sorter?
Upvotes: 13
Views: 25697
Reputation: 887
I used this code to order numerically where the column contains a number and to work even when there are alfabetic values.
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
Upvotes: 0
Reputation: 1
https://www.youtube.com/watch?v=kKeTRPSLxX8 watch this video, it helps a lot
Copying the code from that video:
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
Upvotes: 0
Reputation: 145
Setting your column ValueType to typeof(int) will work, just remember to make sure you put integers into that column. If the rest of your data contains strings, it can be easy to forget to convert your number from a string to an int.
Upvotes: 0
Reputation: 4727
If you are using a DataTable
then you have to set the DataType
on the DataColumn
. Setting ValueType
on the DataGridViewTextBoxColumn
won't help.
You can set it when creating it:
table.Columns.Add("Number", typeof(int));
Upvotes: 5
Reputation: 31
Changing column from string
to int32
might be helpful:
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);
For me, it works. I hope it will help.
Upvotes: 1
Reputation: 63377
You can handle the event SortCompare
to change how the sorting is done, like this:
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
}
}
NOTE: The above code supposes your cell values are convertible to int.
You said your DataGridView
doesn't have DataSource
assigned, that means you Add
the rows manually, so I think you should use numeric
values instead of string
for your cells. That would make the sorting work as you want.
Upvotes: 26