我们有一个DataGridView的自定义实现(它没有做太多,只是处理格式化等)。所有DataGridView控件都绑定到自定义对象列表(System.Generic.List(Of MyObjectName)
)。我的任务是让所有这些网格在多个列上排序(我将从两个开始,如果需要,稍后再次更改)。
目前,通过调用将List(Of T)转换为IBindingList的方法来处理这些网格的排序。然后完成排序:
Private Sub DoSort()
sortedList.Clear()
If sortBy Is Nothing Then
For Each obj As Object In BaseList
sortedList.Add(New ListItem(obj, obj))
Next
Else
If (sortBy.PropertyType Is GetType(Date)) Then
For Each obj As Object In BaseList
sortedList.Add(New ListItem(DirectCast(sortBy.GetValue(obj), Date), obj))
Next
ElseIf (sortBy.PropertyType Is GetType(Integer)) Then
For Each obj As Object In BaseList
sortedList.Add(New ListItem(DirectCast(sortBy.GetValue(obj), Integer), obj))
Next
Else
For Each obj As Object In BaseList
sortedList.Add(New ListItem(sortBy.GetValue(obj), obj))
Next
End If
End If
sortedList.Sort()
m_isSorted = True
RaiseEvent ListChanged(Me, New ListChangedEventArgs(ListChangedType.Reset, 0))
End Sub
我尝试了,但没有为此添加另一列。当被要求将多列排序添加到特定网格时,我欺骗并直接对该列表进行排序。然后我尝试使用相同的代码来修改我们的自定义网格控件:
Protected Overrides Sub OnColumnHeaderMouseClick(e As DataGridViewCellMouseEventArgs)
MyBase.OnColumnHeaderMouseClick(e)
If TypeOf (Me.DataSource) Is IList AndAlso Me.DataSource.GetType().IsGenericType Then
If _strSortcolumn02 = "" Then
_strSortColumn01 = Me.Columns(e.ColumnIndex).Name
_strSortcolumn02 = Me.Columns(e.ColumnIndex).Name
Else
_strSortColumn01 = _strSortcolumn02
_strSortcolumn02 = Me.Columns(e.ColumnIndex).Name
End If
If Me.Columns(e.ColumnIndex).HeaderCell.SortGlyphDirection = SortOrder.Ascending Then
_soSortDirection = Windows.Forms.SortOrder.Descending
Else
_soSortDirection = Windows.Forms.SortOrder.Ascending
End If
'Dim tType As Type = Me.DataSource.GetType()
'Dim typeName As String = String.Format("System.Collections.Generic.List`1[[{0}]], mscorlib", tType.AssemblyQualifiedName)
'Dim lst As New List(Of Type.GetType(typeName))
Dim lst As Object = Me.DataSource
If _soSortDirection = Windows.Forms.SortOrder.Ascending Then
Me.DataSource = lst.OrderBy(Function(x) x.GetType().GetProperty(_strSortColumn01).GetValue(x)). _
ThenBy(Function(x) x.GetType().GetProperty(_strSortcolumn02).GetValue(x)).ToList()
Else
Me.DataSource = lst.OrderByDescending(Function(x) x.GetType().GetProperty(_strSortColumn01).GetValue(x)). _
ThenByDescending(Function(x) x.GetType().GetProperty(_strSortcolumn02).GetValue(x)).ToList()
End If
End If
End Sub
最后一个If Block是给定静态类型List(Of T)时有效的代码。但是,在尝试动态确定类型时,此代码将失败。它以相当令人沮丧的方式这样做,因为在运行时lst
变量是正确的类型,但我在OrderBy上收到错误:
类型' System.MissingMemberException'的第一次机会异常。 发生在Microsoft.VisualBasic.dll
其他信息:公共成员' OrderBy'在类型'列表(Of CustomerInquiryGridBE)'没找到。
重要的是要注意List(Of CustomerInquiryGridBE)
是DataSource的实际类型,当明确提供类型时,这个完全相同的代码可以正常工作。反正有没有让这项工作?
答案 0 :(得分:0)
首先我必须说,我找到了一种方法可以使用数据集> 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
在我的演示者中,我已经有了List(Of T),我不想改变工作代码
这个I类从MSDN中的C#中的一个例子手动转换,在我的情况下工作!
首先在项目中输入这个类: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更改为你的!
然后在我的Form Load()中
在这里,我将我的初始List(Of T)转换为sortableBindingList(Of T)
将此SortableBindingList指定为BindingSource的DataSource,并且不要忘记将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
使用BindingSourceName更改或替换PatientBindingSource
并用yourDataGridViewName替换dgvPacient ..
我有一个小问题,我现在没有时间,使用HeaderCell.SortGlyphDirection,如果我点击一个colun标题,进行排序,然后单击其他列,并按2列排序,但现在我只在最后一列上有GlyphDirection ..
快乐的Codding :)
CristiC777