Если я связываю BindingList (Of FooBar) с источником данных моей сетки данных, элементы управления обновляются всякий раз, когда я добавляю элемент в этот 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.
Теперь, когда я создаю класс FoobarList, который наследует BindingList (Of FooBar) и связать объект FoobarList с сеткой данных, это работает точно так же.
Теперь, когда у меня есть класс, который наследует BindingList (Of T).Когда я связываю объект из этого класса с источником данных сетки и добавляю в него новые элементы, сетка не обновляется.
Мой класс:
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?Понятия не имею, почему это не работает.