如果我将BindingList(Of FooBar)绑定到我的datagrid的数据源,那么只要我将一个项添加到此BindingList,控件就会更新。例如:
Public Class FooBar
Public Property Name As String
Public Property Value As String
End Class
Private obj As BindingList(Of FooBar)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridFooBars.DataSource = obj
End Sub
Private Sub btnNewFooBar(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewFooBar.Click
obj.Add(New FooBar() With { .Name = "Name", .Value = "Value"})
End Sub
每次按下New FooBar按钮时,网格都会添加一个新行。
现在当我创建一个继承BindingList(Of FooBar)并将FoobarList的对象绑定到datagrid的类FoobarList时,它的工作方式完全相同。
现在我有一个继承BindingList(Of T)的Class。当我将一个对象从此类绑定到网格的数据源并向其添加新项时,网格不会更新。
我的课程:
Public Class ProfelList(Of T)
Inherits System.ComponentModel.BindingList(Of T)
Implements IBindingList
Private originalList As List(Of T)
Private sortDirection As ListSortDirection
Private sortProperty As PropertyDescriptor
Private populateBaseList As Action(Of ProfelList(Of T), List(Of T)) = Sub(a, b) a.ResetItems(b)
Shared cachedOrderByExpressions As New Dictionary(Of String, Func(Of List(Of T), IEnumerable(Of T)))()
Public SortMapping As New ProfelSortMapper
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore() As ListSortDirection
Get
Return sortDirection
End Get
End Property
Protected Overrides ReadOnly Property SortPropertyCore() As PropertyDescriptor
Get
Return sortProperty
End Get
End Property
Public Sub New()
originalList = New List(Of T)()
End Sub
Public Sub New(ByVal enumerable As IEnumerable(Of T))
originalList = enumerable.ToList()
populateBaseList(Me, originalList)
End Sub
Public Sub New(ByVal list As List(Of T))
originalList = list
populateBaseList(Me, originalList)
End Sub
Protected Overrides Sub ApplySortCore(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
sortProperty = prop
Dim orderByMethodName = If(sortDirection = ListSortDirection.Ascending, "OrderBy", "OrderByDescending")
Dim cacheKey As String
If SortMapping.ContainsKey(prop.Name.ToLower) Then
cacheKey = Convert.ToString(GetType(T).GUID.ToString & SortMapping(prop.Name.ToLower)) & orderByMethodName
Else
cacheKey = Convert.ToString(GetType(T).GUID.ToString & prop.Name) & orderByMethodName
End If
If Not cachedOrderByExpressions.ContainsKey(cacheKey) Then
CreateOrderByMethod(prop, orderByMethodName, cacheKey)
End If
ResetItems(cachedOrderByExpressions(cacheKey)(originalList).ToList())
ResetBindings()
sortDirection = If(sortDirection = ListSortDirection.Ascending, ListSortDirection.Descending, ListSortDirection.Ascending)
End Sub
Private Sub CreateOrderByMethod(ByVal prop As PropertyDescriptor, ByVal orderByMethodName As String, ByVal cacheKey As String)
Dim sourceParameter = Expression.Parameter(GetType(List(Of T)), "source")
Dim lambdaParameter = Expression.Parameter(GetType(T), "lambdaParameter")
Dim accesedMember As Reflection.PropertyInfo
If SortMapping.ContainsKey(prop.Name.ToLower) Then
accesedMember = GetType(T).GetProperty(SortMapping(prop.Name.ToLower))
Else
accesedMember = GetType(T).GetProperty(prop.Name)
End If
Dim propertySelectorLambda = Expression.Lambda(Expression.MakeMemberAccess(lambdaParameter, accesedMember), lambdaParameter)
Dim orderByMethod = GetType(Enumerable).GetMethods().Where(Function(a) a.Name = orderByMethodName AndAlso a.GetParameters().Length = 2).[Single]().MakeGenericMethod(GetType(T), accesedMember.PropertyType)
Dim orderByExpression = Expression.Lambda(Of Func(Of List(Of T), IEnumerable(Of T)))(Expression.[Call](orderByMethod, New Expression() {sourceParameter, propertySelectorLambda}), sourceParameter)
cachedOrderByExpressions.Add(cacheKey, orderByExpression.Compile())
End Sub
Protected Overrides Sub RemoveSortCore()
ResetItems(originalList)
End Sub
Private Sub ResetItems(ByVal items As List(Of T))
MyBase.ClearItems()
For i As Integer = 0 To items.Count - 1
MyBase.InsertItem(i, items(i))
Next
End Sub
Protected Overrides Sub OnListChanged(ByVal e As ListChangedEventArgs)
originalList = MyBase.Items.ToList()
End Sub
Public Function Find(ByVal match As System.Predicate(Of T)) As T
Return Me.ToList.Find(match)
End Function
Public Function FindAll(ByVal match As System.Predicate(Of T)) As ProfelList(Of T)
Return New ProfelList(Of T)(DirectCast(Me.ToList.FindAll(match), List(Of T)))
End Function
End Class
所以当我这样做时:
Private obj As ProfelList(Of FooBar)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridFooBars.DataSource = obj
End Sub
Private Sub btnNewFooBar(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewFooBar.Click
obj.Add(New FooBar() With { .Name = "Name", .Value = "Value"})
End Sub
数据网格不会更新它的行。数据源obj确实增加了项目。
这个ProfelList(Of FooBar)和BindingList(Of FooBar)或FooBarList之间的区别是什么?我不知道为什么这不起作用。
答案 0 :(得分:0)
我认为你必须实现IObservable来实现这一目标。
答案 1 :(得分:0)
使用不同的BindingListSorter修复它。
Public Class ProfelList(Of T)
Inherits BindingList(Of T)
Implements IRaiseItemChangedEvents
Private m_Sorted As Boolean = False
Private m_SortDirection As ListSortDirection = ListSortDirection.Ascending
Private m_SortProperty As PropertyDescriptor = Nothing
Protected Overrides ReadOnly Property SupportsSearchingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property IsSortedCore() As Boolean
Get
Return m_Sorted
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore() As ListSortDirection
Get
Return m_SortDirection
End Get
End Property
Protected Overrides ReadOnly Property SortPropertyCore() As PropertyDescriptor
Get
Return m_SortProperty
End Get
End Property
Protected Overrides Sub ApplySortCore(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
m_SortDirection = direction
m_SortProperty = prop
Dim comparer As New BOSortComparer(Of T)(prop, direction)
ApplySortInternal(comparer)
End Sub
Private Sub ApplySortInternal(ByVal comparer As BOSortComparer(Of T))
Dim listRef As List(Of T) = TryCast(Me.Items, List(Of T))
If listRef Is Nothing Then
Return
End If
listRef.Sort(comparer)
m_Sorted = True
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
Public Function Find(ByVal match As System.Predicate(Of T)) As T
Return Me.Find(match)
End Function
Public Function FindAll(ByVal match As System.Predicate(Of T)) As ProfelList(Of T)
Return Me.FindAll(match)
End Function
Private Class BOSortComparer(Of J)
Implements IComparer(Of T)
Private m_PropDesc As PropertyDescriptor = Nothing
Private m_Direction As ListSortDirection = ListSortDirection.Ascending
Public Sub New(ByVal propDesc As PropertyDescriptor, ByVal direction As ListSortDirection)
m_PropDesc = propDesc
m_Direction = direction
End Sub
Private Function IComparer_Compare(ByVal x As T, ByVal y As T) As Integer Implements IComparer(Of T).Compare
Dim xValue As Object = m_PropDesc.GetValue(x)
Dim yValue As Object = m_PropDesc.GetValue(y)
Return CompareValues(xValue, yValue, m_Direction)
End Function
Private Function CompareValues(ByVal xValue As Object, ByVal yValue As Object, ByVal direction As ListSortDirection) As Integer
Dim retValue As Integer = 0
If TypeOf xValue Is IComparable Then
retValue = DirectCast(xValue, IComparable).CompareTo(yValue)
ElseIf TypeOf yValue Is IComparable Then
retValue = DirectCast(yValue, IComparable).CompareTo(xValue)
ElseIf xValue IsNot Nothing AndAlso yValue IsNot Nothing AndAlso Not xValue.Equals(yValue) Then
retValue = xValue.ToString().CompareTo(yValue.ToString())
End If
If direction = ListSortDirection.Ascending Then
Return retValue
Else
Return retValue * -1
End If
End Function
End Class
End Class