vb.net - registros - para que se pueda ordenar, un control datagridview debe estar enlazado a un objeto ibindinglist
Ordenar columna alfanumérica de DataView (2)
DataSource de My DataGridView está vinculado a un DataView . El DataView es igual a mi dtBills
DataTable . Al igual que:
Dim View As New DataView
View.Table = DataSet1.Tables("dtBills")
dgvBills.DataSource = View
Tengo varias columnas en este DataGridView. Uno en particular tiene cadenas y enteros como información. Cuando hago clic en el encabezado de columna DataGridView para ordenar la columna, ordena como cadenas como la columna de la izquierda:
''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
¿Cómo haría para ordenar una Columna DataGridView encuadernada al presionar el Encabezado de columna como lo haría normalmente? ¿Debo usar mi DataView
para ayudarme?
La columna está ordenada correctamente como cadenas y supongo que desea ordenarla como números. El problema es que parece que las cadenas que tienes combinan números y caracteres. El resultado es una clasificación bastante compleja para 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")
Entonces se agregan dos nuevas columnas. El primero mantiene ordenando por letras iniciales el segundo para permitir la clasificación por el número contenido en una cadena.
Cuando un DataGridView está enlazado a datos, no es posible utilizar su clasificación y es necesario ordenar los datos de origen. La clasificación es un poco complicada, así que necesito dos columnas auxiliares.
dgvBills.AutoGenerateColumns = False
tbl.Columns.Add(New DataColumn("Scol1", GetType(String)))
tbl.Columns.Add(New DataColumn("Scol2", GetType(Integer)))
El primero contendrá una letra inicial (o cadena vacía). El segundo contendrá solo un número contenido en la cadena. Vamos a ordenar por Scol1, Scol2
.
Ahora configuramos todas las comumns en el modo Programatic
( DataGridViewColumnSortMode Enumeration )
For Each column As DataGridViewColumn In dgvBills.Columns
column.SortMode = DataGridViewColumnSortMode.Programmatic
Next
Y la clasificación personalizada se logra en un controlador de ColumnHeaderMouseClick
( DataGridView.Sort Method (IComparer) ). Utilizaremos la clasificación de la vista subyacente en lugar de la clasificación de la cuadrícula.
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
En {"JobNumber", "JobNumber1"}.Contains ...
es posible establecer columnas que están ordenadas de forma diferente. Otras columnas se ordenan según la cuadrícula las ordena de manera predeterminada o es posible crear otra ordenación personalizada.
Nota: Tengo un ejemplo completamente funcional, pero espero que los fragmentos sean lo suficientemente buenos.