I can't seem to find a current updated answer. The basic functionality works for me, where it will automatically sort a list like:
001.15
1
2
3
some
string
but my biggest issue is if I added a number, say '100', my list will now be:
001.15
1
100
2
3
some
string
I would like to see 100 after 3.
The single column I'm looking to sort by, 'Test ID', will contain strings, integers, and doubles.
I've tried many things, including a method called every time a button is pressed:
private void SortDVG(object sender, DataGridViewSortCompareEventArgs e)
{
if (e.Column.Index == 0)
{
e.SortResult = int.Parse(e.CellValue1.ToString()).CompareTo(int.Parse(e.CellValue2.ToString()));
e.Handled = true;
}
}
with a reference in a button click as
SortDVG(dataGridView1, (DataGridViewSortCompareEventArgs)e);
but this throws a runtime errors because it registers as a mouse event, which makes sense to me.
System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Forms.MouseEventArgs' to type 'System.Windows.Forms.DataGridViewSortCompareEventArgs'.'
and I've even tried just one line (this is what gave me the ordering in the first place)
dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
At a bit of a loss right now and looking to be pointed in the right direction
If your goal is to perform a strict alphanumeric sort on a column that contains mixed types, you can safely achieve this by handling the SortCompare
event and:
e.CellValue1
and e.CellValue2
, converting any null values to string.Empty
.SortResult
by comparing the strings.true
public partial class MainForm : Form
{
public MainForm() => InitializeComponent();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
dataGridView.Columns.Add(new DataGridViewTextBoxColumn
{
Name = "TestId",
AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells,
});
dataGridView.Columns.Add(new DataGridViewTextBoxColumn
{
Name = "Description",
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
});
dataGridView.SortCompare += DataGridView_SortCompare;
dataGridView.Rows.Add(001.15, "First item with decimal");
dataGridView.Rows.Add(1, "Single digit integer");
dataGridView.Rows.Add(100, "Triple digit integer");
dataGridView.Rows.Add(2, "Another single digit integer");
dataGridView.Rows.Add(3, "Yet another single digit integer");
dataGridView.Rows.Add("some string", "String example");
}
private void DataGridView_SortCompare(object? sender, DataGridViewSortCompareEventArgs e)
{
var a = e.CellValue1?.ToString() ?? string.Empty;
var b = e.CellValue2?.ToString() ?? string.Empty;
e.SortResult = a.CompareTo(b);
e.Handled = true;
}
}
Alternative: Sort numbers with numbers
If on the other hand you want a kind of hybrid sort, where "numbers are compared to numbers" then you will get a slightly different result by attempting conversions to double
.
private void DataGridView_SortCompare(object? sender, DataGridViewSortCompareEventArgs e)
{
var a = e.CellValue1?.ToString() ?? string.Empty;
var b = e.CellValue2?.ToString() ?? string.Empty;
if (double.TryParse(a, out double value1) &&
double.TryParse(b, out double value2))
{
e.SortResult = value1.CompareTo(value2);
}
else
{
e.SortResult = a.CompareTo(b);
}
e.Handled = true;
}
NOTE: By default, you can sort on a column by clicking the column header. You can also call DataGridView.Sort(...)
to do the same thing programmatically.