Reputation: 8984
I have a DataGridView bound to a DataTable. I have one column that's a pseudo-int -- you know the kind, where most of the time it has integers but sometimes instead there's an N/A. This column is a varchar, but I want to have it sort like an int column, treating the N/A as a -1.
The DataGridView provides for this -- if it's not bound to a DataTable. If it is bound, it uses the sorting mechanism of the bound object, and DataTables don't expose that functionality.
I can make a custom column in the DataTable with the behaviour I want, but because the DataGridView is bound to the DataTable, it sorts by the column it's displaying. I can make a custom column in the DataGridView, but I need to set the table to virtual mode to sort by that when I already have a solution that mostly works.
How do I make it sort my pseudo-int column as I want - where possible, sorting by int? This scenario seems like it's incredibly common, and I'm sure somewhere it's been provided for.
Upvotes: 4
Views: 4615
Reputation: 2792
Along with Joel Etherton's answer there's an event that you can handle that will let you override the displayed value for a cell.
So, like he said, you'll want two columns. One is a strongly-typed numeric column with -1s for the text values. The other is a hidden text column with the real values (mixed numerics and text values). As-is it will sort properly, but the user will see -1s instead of the actual value.
To fix this we need this code:
Private Sub dgDisplay_CellFormatting(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) _
Handles dgDisplay.CellFormatting
If Not (e.ColumnIndex = dgDisplay.Columns("NumericColumn").Index _
AndAlso e.RowIndex >= 0) Then Exit Sub
Dim newVal As String = dgDisplay.Item("ActualColumn", e.RowIndex).Value
e.Value = newVal
End Sub
This will show the actual text value you want to see, even though the value in the bound DataSource
is just a numeric.
If you're going to do any filtering on the DataView
behind you DataGridView
, make sure you filter on the hidden column.
Upvotes: 0
Reputation: 37533
When I've had to deal with sorting problems similar to this, my favorite method is to add a column to the DataTable and parse the pseudo-int into the sortable int that I want. Then in the DataGridView's binding you can simply hide that column of data, but because it's there you can still sort on it. It adds a little extra data to memory to do this, so depending on the performance hit and the size of your sorted data, this could be a potential issue. Also, anytime the data is modified, you'd need to make sure this extra column is kept in line.
Upvotes: 3
Reputation: 64467
Perhaps you can adapt the code in my blog post to provide an IComparer specific to your int column:
http://adamhouldsworth.blogspot.com/2010/01/bound-datagridview-sorting.html
Upvotes: 0
Reputation: 4867
Why don't you just change the SQL query to return this column as int (-1 for 'N/A') then use a custom formatter for the displayed column?
Upvotes: 1
Reputation: 86344
Try binding to a DataView, not a DataTable, e.g.:
private void SortByTwoColumns()
{
DataView myDataView = DataTable1.DefaultView;
myDataView.Sort = "State, ZipCode DESC";
myGridView.DataSource = myDataView;
}
You have a few choices of dealing with the N/A data - SELECT statement, RowPrePaint event, and more.
Upvotes: 1