Прежде всего, я должен сказать, что нашел способ сделать с DataSet> DataTable для приложения с прямым подключением к базе данных.
Как мы уже знаем из MSDN:
*To support sorting, the underlying list must implement the IBindingList or IBindingListView, interfaces. This capability can be queried through the SupportsSorting property. Multicolumn sorting is available when the SupportsAdvancedSorting property is true.
Setting the Sort property will change the internal list depending on its type:
If the list is of type IBindingList, the IBindingList.SortProperty and IBindingList.SortDirection properties are set in the internal list.
If the list is of type IBindingListView, the IBindingListView.SortDescriptions property is set.*
Но у меня есть приложение Winform с помощью MVP модели с EF6
В моем предъявитель у меня уже был список (Of T), и я не хочу, чтобы изменить рабочий код.
Этот класс I, преобразованный вручную из примера на C# из MSDN, в моем случае работает!
Первый InPort это classs в проекте: SortableBindingList
Imports System.ComponentModel
Imports System.Reflection
Namespace Repository
Public Class SortableBindingList(Of T)
Inherits BindingList(Of T)
Private sortedList As ArrayList
Private unsortedItems As ArrayList
Private isSortedValue As Boolean
Public Sub New()
End Sub
Public Sub New(list As IList(Of T))
For Each o As Object In list
Me.Add(DirectCast(o, T))
Next
End Sub
Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides Function FindCore(prop As PropertyDescriptor, key As Object) As Integer
Dim propInfo As PropertyInfo = GetType(T).GetProperty(prop.Name)
Dim item As T
If Not (key Is Nothing) Then
Dim i As Integer = 0
While i < Count
item = DirectCast(Items(i), T)
If propInfo.GetValue(item, Nothing).Equals(key) Then
Return i
End If
System.Threading.Interlocked.Increment(i)
End While
End If
Return -1
End Function
Public Function Find([property] As String, key As Object) As Integer
Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
Dim prop As PropertyDescriptor = properties.Find([property], True)
If IsNothing(prop) Then
Return -1
Else
Return FindCore(prop, key)
End If
End Function
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property IsSortedCore() As Boolean
Get
Return isSortedValue
End Get
End Property
Private sortDirectionValue As ListSortDirection
Private sortPropertyValue As PropertyDescriptor
Protected Overrides Sub ApplySortCore(prop As PropertyDescriptor, direction As ListSortDirection)
sortedList = New ArrayList()
'// Check to see if the property type we are sorting by implements
'// the IComparable interface.
Dim interfaceType As Type = prop.PropertyType.GetInterface("IComparable")
If interfaceType = Nothing AndAlso prop.PropertyType.IsValueType Then
Dim underlyingType As Type = Nullable.GetUnderlyingType(prop.PropertyType)
If Not (underlyingType Is Nothing) Then
interfaceType = underlyingType.GetInterface("IComparable")
End If
End If
If Not (interfaceType Is Nothing) Then
'// If so, set the SortPropertyValue and SortDirectionValue.
sortPropertyValue = prop
sortDirectionValue = direction
Dim query As IEnumerable(Of T) = MyBase.Items
If direction = ListSortDirection.Ascending Then
query = query.OrderBy(Function(i) prop.GetValue(i))
Else
query = query.OrderByDescending(Function(i) prop.GetValue(i))
End If
Dim newIndex As Integer = 0
For Each item As Object In query
Me.Items(newIndex) = DirectCast(item, T)
System.Math.Max(System.Threading.Interlocked.Increment(newIndex), newIndex - 1)
Next
isSortedValue = True
Me.OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
Else
Throw New NotSupportedException("Cannot sort by " + prop.Name + ". This" + prop.PropertyType.ToString() + " does not implement IComparable")
End If
End Sub
Protected Overrides Sub RemoveSortCore()
Dim position As Integer
Dim temp As Object
If Not (unsortedItems Is Nothing) Then
Dim i As Integer = 0
While i < unsortedItems.Count
position = Me.Find("LastName", unsortedItems(i).[GetType]().GetProperty("LastName").GetValue(unsortedItems(i), Nothing))
If position > 0 AndAlso position <> i Then
temp = Me(i)
Me(i) = Me(position)
Me(position) = DirectCast(temp, T)
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
ElseIf position = i Then
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
Else
unsortedItems.RemoveAt(i)
End If
End While
isSortedValue = False
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End If
End Sub
Public Sub RemoveSort()
RemoveSortCore()
End Sub
Protected Overrides ReadOnly Property SortPropertyCore() As PropertyDescriptor
Get
Return sortPropertyValue
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore() As ListSortDirection
Get
Return sortDirectionValue
End Get
End Property
Public Sub myPublicSort(ByRef prop As PropertyDescriptor, direction As ListSortDirection)
ApplySortCore(prop, direction)
End Sub
End Class
End Namespace
Изменение Namspace к вашему!
Тогда в моей формы Load()
Здесь я преобразовал свой первоначальный список (Of T) для sortableBindingList (Of T)
Назначьте этот SortableBindingList как DataSource из BindingSource, не забудьте установить DataGridView DataSource в YourBindingSource (в моем случае PatientBindingSource)
For Each item As Patient In _presenter.GetAllPatient() ' my List(Of Patients)
sortableBList.Add(item)
Next
Try
PatientBindingSource.DataSource = sortableBList '_presenter.listaPacienti
Catch ex As ArgumentException
Console.WriteLine(ex)
End Try
PatientBindingSource.ResetBindings(False)
После этого Добавить
'this is for Programatic Sort
Private Sub dgvPacient_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles dgvPacient.DataBindingComplete
For Each Column As DataGridViewColumn In dgvPacient.Columns
Column.SortMode = DataGridViewColumnSortMode.Programmatic
Next Column
End Sub
'click on Column Header to sort
Private Sub dgvPacient_ColumnHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles dgvPacient.ColumnHeaderMouseClick
If isInitDone Then
Try
Debug.WriteLine("click pe header !")
Dim ColumnNameBruteFromDGV As String = dgvPacient.Columns(e.ColumnIndex).Name
Dim ColumnName As String = ColumnNameBruteFromDGV.Replace("DataGridViewTextBoxColumn", "")
Dim lastColumnDir As String = ""
Dim SortDirection As ListSortDirection
If IsNothing(PatientBindingSource.Sort) Then
SortDirection = ListSortDirection.Ascending
PatientBindingSource.Sort = "LastName" & " ASC"
Else
If PatientBindingSource.Sort.Contains(lastColumnName) Then
If PatientBindingSource.Sort.Contains("DESC") Then
PatientBindingSource.Sort = lastColumnName & lastColumnDir & " " & ColumnName & " ASC"
SortDirection = ListSortDirection.Ascending
Else
PatientBindingSource.Sort = lastColumnName & lastColumnDir & " " & ColumnName & " DESC"
SortDirection = ListSortDirection.Descending
End If
Else
If PatientBindingSource.Sort.Contains("DESC") Then
lastColumnName = ColumnName
lastColumnDir = " DESC"
PatientBindingSource.Sort = lastColumnName & lastColumnDir
SortDirection = ListSortDirection.Descending
Else
lastColumnName = ColumnName
lastColumnDir = " ASC"
PatientBindingSource.Sort = lastColumnName & lastColumnDir
SortDirection = ListSortDirection.Ascending
End If
End If
End If
' ColumnName
dgvPacient.Columns(e.ColumnIndex).HeaderCell.SortGlyphDirection = _
If(SortDirection = ListSortDirection.Ascending, _
SortOrder.Ascending, _
SortOrder.Descending _
)
Catch ex As ArgumentException
Debug.WriteLine("dgvPacient_ColumnHeaderMouseClick Exception : " & ex.Message)
End Try
End If
End Sub
изменить или заменить PatientBindingSource с BindingSourceName
и заменить dgvPacient с yourDataGridViewName ..
У меня есть немного issuse, что у меня нет времени сейчас, с HeaderCell.SortGlyphDirection, если я нажимаю на заголовке Colun, сортируется, и нажмите на другой колонке, и сортируется по 2 колонки, но теперь у меня есть GlyphDirection только на последней колонке ..
Happy Codding :)
CristiC777
http://www.codeproject.com/Articles/19867/How- To-Allow-To-Sort-By-Multiple-Columns-in-Custom – CristiC777
BindingSource.Sort = "Column1 ASC, Column2 DESC, Column 3 ASC"; – CristiC777
@ CristiC777 Я также попробовал BindingSource. Это не ошибка, но она тоже ничего не сделала. –