#vb.net #datagridview #datasource
#vb.net #datagridview #источник данных
Вопрос:
Если я привязываю список привязок (из FooBar) к источнику данных моей сетки данных, элементы управления обновляются всякий раз, когда я добавляю элемент в этот список привязок. Например:
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 (от FooBar) и привязываю объект FoobarList к datagrid, это работает точно так же.
Теперь, когда у меня есть класс, который наследует BindingList (из 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 amp; SortMapping(prop.Name.ToLower)) amp; orderByMethodName
Else
cacheKey = Convert.ToString(GetType(T).GUID.ToString amp; prop.Name) amp; 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 не обновляет его строки. Объект источника данных действительно увеличивается в элементах.
В чем разница между этим ProfelList (из FooBar) и BindingList (из FooBar) или FooBarList FooBarList? Я понятия не имею, почему это не работает.
Ответ №1:
Я думаю, вам нужно реализовать IObservable для достижения этого.
Комментарии:
1. Тогда почему это работает, когда я делаю, что Class FoobarList наследует BindingList (от FooBar) Конечный класс
Ответ №2:
Исправлено с помощью другого 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