WPF:我需要实现什么才能使扩展 IList(of T) 可绑定?

发布于 2024-10-22 06:18:18 字数 5105 浏览 1 评论 0原文

我正在扩展 IList,以便可以跟踪对列表所做的更改(更新、插入和删除)。
一切正常,但我无法将任何 ItemsControl 绑定到它。

Public Class TrackedList(Of T)
    Implements IList(Of T), INotifyCollectionChanged

    Public Sub New(Lista As IList(Of T))
        m_inner = Lista
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
    End Sub

    Private m_inner As IList(Of T)
    Public ReadOnly Property Inner() As IList(Of T)
        Get
            If m_inner Is Nothing Then
                m_inner = New List(Of T)()
            End If
            Return m_inner
        End Get
    End Property

    Private m_Updates As IList(Of T)
    Public ReadOnly Property Updates() As IList(Of T)
        Get
            If m_Updates Is Nothing Then
                m_Updates = New List(Of T)()
            End If
            Return m_Updates
        End Get
    End Property

    Private m_Inserts As IList(Of T)
    Public ReadOnly Property Inserts() As IList(Of T)
        Get
            If m_Inserts Is Nothing Then
                m_Inserts = New List(Of T)()
            End If
            Return m_Inserts
        End Get
    End Property

    Private m_Deletes As IList(Of T)
    Public ReadOnly Property Deletes() As IList(Of T)
        Get
            If m_Deletes Is Nothing Then
                m_Deletes = New List(Of T)()
            End If
            Return m_Deletes
        End Get
    End Property

    'Propietary methods'
    Public Sub ItemUpdated(ByVal item As T)
        If Not Updates.Contains(item) Then Updates.Add(item)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace))
    End Sub

    Public Sub FlushChanges()
        m_Updates = Nothing
        m_Inserts = Nothing
        m_Updates = Nothing
    End Sub


    Public Sub Add(ByVal item As T) Implements System.Collections.Generic.ICollection(Of T).Add
        Inner.Add(item)
        Inserts.Add(item)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add))
    End Sub

    Public Sub Clear() Implements System.Collections.Generic.ICollection(Of T).Clear
        If m_inner IsNot Nothing Then
            Inner.Clear()
        End If
    End Sub

    Public Function Contains(ByVal item As T) As Boolean Implements System.Collections.Generic.ICollection(Of T).Contains
        Return Inner.Contains(item)
    End Function

    Public Sub CopyTo(ByVal array() As T, ByVal arrayIndex As Integer) Implements System.Collections.Generic.ICollection(Of T).CopyTo
        Inner.CopyTo(array, arrayIndex)
    End Sub

    Public ReadOnly Property Count() As Integer Implements System.Collections.Generic.ICollection(Of T).Count
        Get
            Return Inner.Count
        End Get
    End Property

    Public ReadOnly Property IsReadOnly() As Boolean Implements System.Collections.Generic.ICollection(Of T).IsReadOnly
        Get
            Return Inner.IsReadOnly
        End Get
    End Property

    Public Function Remove(ByVal item As T) As Boolean Implements System.Collections.Generic.ICollection(Of T).Remove
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove))
        Deletes.Add(item)
        Return Inner.Remove(item)

    End Function


    Public Function IndexOf(ByVal item As T) As Integer Implements System.Collections.Generic.IList(Of T).IndexOf
        Return Inner.IndexOf(item)
    End Function

    Public Sub Insert(ByVal index As Integer, ByVal item As T) Implements System.Collections.Generic.IList(Of T).Insert
        Inserts.Add(item)
        Inner.Insert(index, item)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add))
    End Sub

    Default Public Property Item(ByVal index As Integer) As T Implements System.Collections.Generic.IList(Of T).Item
        Get
            Return Inner(index)
        End Get
        Set(ByVal value As T)
            Inner(index) = value
        End Set
    End Property

    Public Sub RemoveAt(ByVal index As Integer) Implements System.Collections.Generic.IList(Of T).RemoveAt
        Deletes.Add(Inner(index))
        Inner.RemoveAt(index)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove))
    End Sub

    Public Function GetEnumerator1() As System.Collections.Generic.IEnumerator(Of T) Implements System.Collections.Generic.IEnumerable(Of T).GetEnumerator
        Return Inner.GetEnumerator()
    End Function

    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return DirectCast(Inner, IEnumerable).GetEnumerator()
    End Function


    Public Event CollectionChanged(sender As Object, e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Implements System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged

End Class

我需要做什么才能使列表可绑定?

I'm extending IList so I can track the changes made to the list (updates, inserts and deletes).
Everything is ok, but I can not bind any ItemsControl to it.

Public Class TrackedList(Of T)
    Implements IList(Of T), INotifyCollectionChanged

    Public Sub New(Lista As IList(Of T))
        m_inner = Lista
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
    End Sub

    Private m_inner As IList(Of T)
    Public ReadOnly Property Inner() As IList(Of T)
        Get
            If m_inner Is Nothing Then
                m_inner = New List(Of T)()
            End If
            Return m_inner
        End Get
    End Property

    Private m_Updates As IList(Of T)
    Public ReadOnly Property Updates() As IList(Of T)
        Get
            If m_Updates Is Nothing Then
                m_Updates = New List(Of T)()
            End If
            Return m_Updates
        End Get
    End Property

    Private m_Inserts As IList(Of T)
    Public ReadOnly Property Inserts() As IList(Of T)
        Get
            If m_Inserts Is Nothing Then
                m_Inserts = New List(Of T)()
            End If
            Return m_Inserts
        End Get
    End Property

    Private m_Deletes As IList(Of T)
    Public ReadOnly Property Deletes() As IList(Of T)
        Get
            If m_Deletes Is Nothing Then
                m_Deletes = New List(Of T)()
            End If
            Return m_Deletes
        End Get
    End Property

    'Propietary methods'
    Public Sub ItemUpdated(ByVal item As T)
        If Not Updates.Contains(item) Then Updates.Add(item)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace))
    End Sub

    Public Sub FlushChanges()
        m_Updates = Nothing
        m_Inserts = Nothing
        m_Updates = Nothing
    End Sub


    Public Sub Add(ByVal item As T) Implements System.Collections.Generic.ICollection(Of T).Add
        Inner.Add(item)
        Inserts.Add(item)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add))
    End Sub

    Public Sub Clear() Implements System.Collections.Generic.ICollection(Of T).Clear
        If m_inner IsNot Nothing Then
            Inner.Clear()
        End If
    End Sub

    Public Function Contains(ByVal item As T) As Boolean Implements System.Collections.Generic.ICollection(Of T).Contains
        Return Inner.Contains(item)
    End Function

    Public Sub CopyTo(ByVal array() As T, ByVal arrayIndex As Integer) Implements System.Collections.Generic.ICollection(Of T).CopyTo
        Inner.CopyTo(array, arrayIndex)
    End Sub

    Public ReadOnly Property Count() As Integer Implements System.Collections.Generic.ICollection(Of T).Count
        Get
            Return Inner.Count
        End Get
    End Property

    Public ReadOnly Property IsReadOnly() As Boolean Implements System.Collections.Generic.ICollection(Of T).IsReadOnly
        Get
            Return Inner.IsReadOnly
        End Get
    End Property

    Public Function Remove(ByVal item As T) As Boolean Implements System.Collections.Generic.ICollection(Of T).Remove
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove))
        Deletes.Add(item)
        Return Inner.Remove(item)

    End Function


    Public Function IndexOf(ByVal item As T) As Integer Implements System.Collections.Generic.IList(Of T).IndexOf
        Return Inner.IndexOf(item)
    End Function

    Public Sub Insert(ByVal index As Integer, ByVal item As T) Implements System.Collections.Generic.IList(Of T).Insert
        Inserts.Add(item)
        Inner.Insert(index, item)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add))
    End Sub

    Default Public Property Item(ByVal index As Integer) As T Implements System.Collections.Generic.IList(Of T).Item
        Get
            Return Inner(index)
        End Get
        Set(ByVal value As T)
            Inner(index) = value
        End Set
    End Property

    Public Sub RemoveAt(ByVal index As Integer) Implements System.Collections.Generic.IList(Of T).RemoveAt
        Deletes.Add(Inner(index))
        Inner.RemoveAt(index)
        RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove))
    End Sub

    Public Function GetEnumerator1() As System.Collections.Generic.IEnumerator(Of T) Implements System.Collections.Generic.IEnumerable(Of T).GetEnumerator
        Return Inner.GetEnumerator()
    End Function

    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        Return DirectCast(Inner, IEnumerable).GetEnumerator()
    End Function


    Public Event CollectionChanged(sender As Object, e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) Implements System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged

End Class

What do I need to do the make the list Bindable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

秋千易 2024-10-29 06:18:18

如果您不能仅继承 ObservableCollection,您可能真的想要实施INotifyCollectionChanged

If you can't just inherit from ObservableCollection, you probably really want to implement INotifyCollectionChanged.

无敌元气妹 2024-10-29 06:18:18

问题不在类中,它甚至不需要实现 INotifyCollectionChanged

问题出在中间控件中,该控件具有用于桥接绑定的 DependencyProperty 事实

Public Shared ReadOnly ItemsProperty As DependencyProperty = _
    DependencyProperty.Register("Items", GetType(IList), GetType(MainWindowViewModel))

Public Property Items As IList
    Set(ByVal value As IList)
        SetValue(ItemsProperty, value)
    End Set
    Get
        Return DirectCast(GetValue(ItemsProperty), IList)
    End Get
End Property

证明,更改IEnumerable 的依赖属性解决了这个问题。

The trouble wasn't in the class, it does not even need to implement INotifyCollectionChanged

The problem was in a intermediate control who has a DependencyProperty for bridging the binding

Public Shared ReadOnly ItemsProperty As DependencyProperty = _
    DependencyProperty.Register("Items", GetType(IList), GetType(MainWindowViewModel))

Public Property Items As IList
    Set(ByVal value As IList)
        SetValue(ItemsProperty, value)
    End Set
    Get
        Return DirectCast(GetValue(ItemsProperty), IList)
    End Get
End Property

Turns out that changing the dependency property to IEnumerable solved the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文