Pero cuando se usa listas genéricas como origen de datos para un Datagridview la posibilidad de ordenación queda deshabilitado.
para solucionar este problema se debe crear una clase SortableBindingList.vb que herede de BindingList
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Text
Imports System.Reflection
Public Class SortableBindingList(Of T)
Inherits BindingList(Of T)
Private _isSorted As Boolean
Private _sortDirection As ListSortDirection
Private _sortProperty As PropertyDescriptor
'This override shows the binded object, that our list supports sorting
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
'And that it can sort bi-directional
Protected Overrides ReadOnly Property SortDirectionCore() As ListSortDirection
Get
Return _sortDirection
End Get
End Property
'And that it can sort by T typed object's properties
Protected Overloads Overrides ReadOnly Property SortPropertyCore() As PropertyDescriptor
Get
Return _sortProperty
End Get
End Property
'This is the method, what gets called when the sort event occurs in the bound object
Protected Overloads Overrides Sub ApplySortCore(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
Dim items As List(Of T) = TryCast(Me.Items, List(Of T))
If items IsNot Nothing Then
Dim pc As New PropertyComparer(Of T)(prop.Name, direction)
items.Sort(pc)
_isSorted = True
_sortDirection = direction
_sortProperty = prop
Else
_isSorted = False
End If
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
'This shows if our list is already sorted or not
Protected Overloads Overrides ReadOnly Property IsSortedCore() As Boolean
Get
Return _isSorted
End Get
End Property
'Removing the sort
Protected Overrides Sub RemoveSortCore()
_isSorted = False
End Sub
'Sub New(ByVal list As ICollection(Of T))
' MyBase.New(list)
'End Sub
End Class
Public Class PropertyComparer(Of T)
Implements IComparer(Of T)
Private _property As PropertyInfo
Private _sortDirection As ListSortDirection
Public Sub New(ByVal sortProperty As String, ByVal sortDirection As ListSortDirection)
_property = GetType(T).GetProperty(sortProperty)
Me._sortDirection = sortDirection
End Sub
Public Function Compare(ByVal x As T, ByVal y As T) As Integer Implements IComparer(Of T).Compare
Dim valueX As Object = _property.GetValue(x, Nothing)
Dim valueY As Object = _property.GetValue(y, Nothing)
If _sortDirection = ListSortDirection.Ascending Then Return Comparer.[Default].Compare(valueX, valueY)
Return Comparer.[Default].Compare(valueY, valueX)
End Function
End Class
SortableBindingList reemplazará a List(Of ) o a cualquier tipo de coleccion que use. Como este ejemplo lo hago de la base de datos Northwind y la tabla Categories tengo que crear una clase con las columnas que deseo consultar.
procedemos a crear la clase Categories.vb
Public Class Categories
Private lCategoryId As String = String.Empty
Private lCategoryName As String = String.Empty
Private lDescription As String = String.Empty
Public Property CategoryId() As String
Get
Return lCategoryId
End Get
Set(ByVal value As String)
lCategoryId = value
End Set
End Property
Public Property CategoriName() As String
Get
Return lCategoryName
End Get
Set(ByVal value As String)
lCategoryName = value
End Set
End Property
Public Property Description() As String
Get
Return lDescription
End Get
Set(ByVal value As String)
lDescription = value
End Set
End Property
End Class
ahora voy a crear una clase ListCategories.vb que herede de SortableBindingList
Public Class ListCategories
Inherits SortableBindingList(Of Categories)
Sub New()
End Sub
End Class
ahora cuando quiera usar una colección de la clase categories.vb solo tengo que instanciar de la clase ListCategories y ya no de List(Of)
ejmplo:
Dim List as New ListCategories
o
Dim List as New SortableBindingList(Of categories)
lo cual reemplazaria a:
Dim List as New List(Of categories)
Ahora creamos un formulario con un datagridview y consultamos de la base de datos Northwind y la tabla Categories y colocamos el siguiente código en el load del formulario.
Dim lList As New ListCategories
Using cn As New SqlConnection("Data Source=XXXX;Initial Catalog=BD;User ID=sa;Password=xyzxyz")
Using cmd As New SqlCommand
cmd.CommandType = CommandType.Text
cmd.CommandText = "select categoryId, categoryName, Description from Categories"
cmd.Connection = cn
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader
If dr.HasRows = True Then
Dim lColumn0 As Integer = dr.GetOrdinal("categoryId")
Dim lColumn1 As Integer = dr.GetOrdinal("categoryName")
Dim lColumn2 As Integer = dr.GetOrdinal("Description")
Dim lCount As Integer = dr.FieldCount - 1
Dim Values(lCount) As Object
Dim lEntidad As Categories
While dr.Read
dr.GetValues(Values)
lEntidad = New Categories
lEntidad.CategoryId = Values(lColumn0)
lEntidad.CategoriName = Values(lColumn1)
lEntidad.Description = Values(lColumn2)
lList.Add(lEntidad)
End While
End If
End Using
cn.Close()
End Using
End Using
DataGridView1.DataSource = lList
ahora ejecutamos y podemos visualizar que el datagridview se carga teniendo asociado como origen de datos una lista generica de tipo SortableBindingList y tambien podemos apreciar que se puede ordenar las columnas haciendo click en ellas.
espero haya sido de utilidad, hasta la próxima.
4 comentarios:
SOS UN CAPO FUNCIONA A LA PERFECCION. GRACIASSS!!!!
GRACIASSSSSSSSSSSSSS!
Estimado MILTON. La verdad que no se como darte las gracias.
Simplemente EXCELENTE!!!
Mil mil gracias.
Te mando un abrazo.
Gracias por compartir, me ha venido genial, mil gracias.
Publicar un comentario