Reputation: 4938
My DataGridView's DataSource is bound to a DataView. The DataView is equal to my dtBills
DataTable. Like so:
Dim View As New DataView
View.Table = DataSet1.Tables("dtBills")
dgvBills.DataSource = View
I have multiple columns in this DataGridView. One in particular has strings and integers as information. When I click on the DataGridView Column Header to sort the column, it sorts as strings like the column on the left:
'Curr Col >>> ' Wanted Result
10001 >>> 10001
100012 >>> 11000
11000 >>> 12000
110049 >>> 100012
12000 >>> 110049
E-1234 >>> E-1234
T-12345 >>> T-1235
T-1235 >>> T-12345
How would I go about sorting a bound DataGridView Column when pressing on the Column Header as I normally would? Should I use my DataView
to help me out?
Upvotes: 4
Views: 4135
Reputation: 5139
When a DataGridView is databound it is not possible to use its sorting and it is necessary to sort source data. The sorting is a bit complicated so I need two helper columns.
dgvBills.AutoGenerateColumns = False
tbl.Columns.Add(New DataColumn("Scol1", GetType(String)))
tbl.Columns.Add(New DataColumn("Scol2", GetType(Integer)))
The first one will contain a leading letters (or empty string). The second will contain only a number contained in the string. We will sort by Scol1, Scol2
.
Now we set all comumns to Programatic
mode (DataGridViewColumnSortMode Enumeration)
For Each column As DataGridViewColumn In dgvBills.Columns
column.SortMode = DataGridViewColumnSortMode.Programmatic
Next
And custom sorting is achieved in a handler of ColumnHeaderMouseClick
(DataGridView.Sort Method (IComparer)). We will use sorting of the underlying view instead of the Grid sorting.
Private Sub dgvBills_ColumnHeaderMouseClick(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dgvBills.ColumnHeaderMouseClick
Dim newColumn As DataGridViewColumn = dgvBills.Columns(e.ColumnIndex)
Dim direction As ListSortDirection
Dim Modifier As String = ""
If newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending Then
direction = ListSortDirection.Descending
Modifier = " desc"
Else
direction = ListSortDirection.Ascending
End If
Dim View As DataView = dgvBills.DataSource
If {"JobNumber", "JobNumber1"}.Contains(dgvBills.Columns(e.ColumnIndex).Name) Then
View.Table.Columns("Scol2").Expression = String.Format("Convert(iif (substring({0},1,2) like '*-',substring({0},3,len({0})-1),{0}), 'System.Int32')", dgvBills.Columns(e.ColumnIndex).Name)
View.Table.Columns("Scol1").Expression = String.Format("iif (substring({0},1,2) like '*-',substring({0},1,2),'')", dgvBills.Columns(e.ColumnIndex).Name)
View.Sort = String.Format("Scol1 {0},Scol2 {0}", Modifier)
Else
dgvBills.Sort(newColumn, direction)
End If
If direction = ListSortDirection.Ascending Then
newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending
Else
newColumn.HeaderCell.SortGlyphDirection = SortOrder.Descending
End If
End Sub
In {"JobNumber", "JobNumber1"}.Contains ...
is possible to set columns which are sorted differntly. Other columns are sorted as the Grid sorts them by default or it is possible to create another custom sorting.
Note: I have fully working example but I hope that fragments are good enough.
Upvotes: 1
Reputation: 5139
The column is sorted correctly as strings and I suppose you want to sort it as numbers. The problem is that it seems that the strings you have combine numbers and characters. The result is necessity rather complex sorting for a DataView
.
Dim tbl As New DataTable("dtBills")
Dim DataSet1 As New DataSet
DataSet1.Tables.Add(tbl)
tbl.Columns.Add(New DataColumn("MyCol", GetType(String)))
Dim vals As String() = {"10001", "100012", "11000", "110049", "12000", "E-1234", "T-12345", "T-1235"}
For qq = 0 To vals.Length - 1
Dim row As DataRow
row = tbl.NewRow
row(0) = vals(qq)
tbl.Rows.Add(vals(qq))
Next
tbl = DataSet1.Tables("dtBills")
tbl.Columns.Add(New DataColumn("Scol2", GetType(Integer)) With {.Expression = "Convert(iif (substring(MyCol,1,2) like '*-',substring(MyCol,3,len(MyCol)-1),MyCol), 'System.Int32')"})
tbl.Columns.Add(New DataColumn("Scol1", GetType(String)) With {.Expression = "iif (substring(MyCol,1,2) like '*-',substring(MyCol,1,2),'')"})
Dim View As New DataView(tbl)
View.Sort = "Scol1,Scol2"
View.Table = DataSet1.Tables("dtBills")
So two new columns are added. The first maintain sorting by initial letters the second to enable sorting by the number contained in the a string.
Upvotes: 1