如果我將BindingList(Of FooBar)綁定到我的數據網格的數據源,則只要向該BindingList添加項目,控件就會更新。例如:作爲數據源的CustomObject不更新控制
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並將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
的DataGrid不更新行。數據源obj確實增加了項目。
這個ProfelList(Of FooBar)和BindingList(Of FooBar)或FooBarList有什麼不同?我不知道爲什麼這不起作用。
那麼爲什麼當我做FoobarList類繼承BindingList(Of FooBar)End Class – 2011-05-17 09:18:21