Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 在项目属性更改时更新ObservableCollection_Vb.net_Observablecollection - Fatal编程技术网

Vb.net 在项目属性更改时更新ObservableCollection

Vb.net 在项目属性更改时更新ObservableCollection,vb.net,observablecollection,Vb.net,Observablecollection,我正在尝试获取一个ObservableCollection,以便在项目的属性更改时触发CollectionChanged事件。我使用了中的代码来执行此操作,但可能是在将C#翻译为Vb.net时出错了。在任何情况下,item\u PropertyChanged都不会触发。我错过了什么 代码: 编辑: Bjørn和Liero都提供了很好的答案,在这种情况下,我发现很难将其中一个标记为正确,而不是另一个,因此我选择Bjørn的帖子的理由是,虽然Bjørn的帖子回答了我提出的问题,但我标记了Liero的

我正在尝试获取一个
ObservableCollection
,以便在项目的属性更改时触发
CollectionChanged
事件。我使用了中的代码来执行此操作,但可能是在将C#翻译为Vb.net时出错了。在任何情况下,
item\u PropertyChanged
都不会触发。我错过了什么

代码:

编辑:


Bjørn和Liero都提供了很好的答案,在这种情况下,我发现很难将其中一个标记为正确,而不是另一个,因此我选择Bjørn的帖子的理由是,虽然Bjørn的帖子回答了我提出的问题,但我标记了Liero的答案,因为他的评论引导我找到了适合我的场景的最佳解决方案。

如果值与支持字段不同,则需要在每个属性的setter中引发property changed事件

Public Property Foo() As String
    Get
        Return Me.m_foo
    End Get
    Set(value As String)
        If (value <> Me.m_foo) Then
            Me.m_foo = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Foo"))
        End If
    End Set
End Property
而且,正如他/她所正确指出的,您最好重写
插入项
设置项
删除项
清除项
,而不是处理
集合更改
事件

Public Class TrulyObservableCollection(Of T As INotifyPropertyChanged)
    Inherits ObservableCollection(Of T)

    Protected Overrides Sub InsertItem(index As Integer, item As T)
        MyBase.InsertItem(index, item)
        Me.HookItem(item)
    End Sub

    Protected Overrides Sub SetItem(index As Integer, newItem As T)
        Dim oldItem As T = Me.Items(index)
        MyBase.SetItem(index, newItem)
        Me.UnhookItem(oldItem)
        Me.HookItem(newItem)
    End Sub

    Protected Overrides Sub RemoveItem(index As Integer)
        Dim item As T = Me.Items(index)
        MyBase.RemoveItem(index)
        Me.UnhookItem(item)
    End Sub

    Protected Overrides Sub ClearItems()
        For Each item As T In Me.Items
            Me.UnhookItem(item)
        Next
        MyBase.ClearItems()
    End Sub

    Private Sub HookItem(item As T)
        If (Not item Is Nothing) Then AddHandler item.PropertyChanged, AddressOf Me.HandleItemPropertyChanged
    End Sub

    Private Sub UnhookItem(item As T)
        If (Not item Is Nothing) Then RemoveHandler item.PropertyChanged, AddressOf Me.HandleItemPropertyChanged
    End Sub

    Private Sub HandleItemPropertyChanged(sender As Object, e As PropertyChangedEventArgs)
        Me.OnCollectionChanged(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
    End Sub

End Class

您是对的,您需要附加到每个项目的PropertyChanged事件。但订阅时不能依赖CollectionChanged事件。例如,清除集合时,旧项不在事件参数中。也可以将项目传递给ObservableCollection

更好的方法是重写方法
ClearItems
RemoveItem
InsertItem
SetItem

已经有一些实现,例如:

当然,我不久前也写过自己的:) 但由于WPF引入了实时成型,我并不真正需要它:


编辑:不要忘记在属性更改时触发propertychanged事件,就像@Bjørn Roger Kringsjå建议的那样。根据评论,您的问题不在observablecollection中,而是类的INotifyPropertyChanged实现

谢谢您的信息。我没有意识到生活塑造,所以我一直在阅读它。不过,我想知道,在我的场景中,我有一个静态的机器列表,希望以设定的间隔更新状态,并将这些更改反映在
数据网格中,我应该如何实现实时整形?我不是真的分组、过滤或排序,所以这是正确的方法吗?应该可以。你根本不需要可观的收集。CollectionChanged事件只有在您需要从集合中添加/删除项并在datagrid中反映时才有意义。ObervableCollection.PropertyChanged仅通知Count属性已更改。若您只想在状态改变时更新datagrid中的单元格,则需要在“机器”实体中触发propertychanged事件。绑定将自动更新单元格。如果没有问题,问题是在其他地方,但肯定不是在集合更改事件中,谢谢。我似乎走错了方向。按照您的建议,在我的类属性设置器中启动
PropertyChanged
,使其正常工作。
Public Class Edm
    Implements INotifyPropertyChanged

    Public Sub New(ip As String, status As String)
        Me.m_ip = ip
        Me.m_status = status
    End Sub

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Public Property Ip() As String
        Get
            Return Me.m_ip
        End Get
        Set(value As String)
            If (value <> Me.m_ip) Then
                Me.m_ip = value
                Me.NotifyPropertyChanged("Ip")
            End If
        End Set
    End Property

    Public Property Status() As String
        Get
            Return Me.m_status
        End Get
        Set(value As String)
            If (value <> Me.m_status) Then
                Me.m_status = value
                Me.NotifyPropertyChanged("Status")
            End If
        End Set
    End Property

    Private Sub NotifyPropertyChanged(propertyName As String)
        Me.OnPropertyChanged(New PropertyChangedEventArgs(propertyName))
    End Sub

    Protected Overridable Sub OnPropertyChanged(e As PropertyChangedEventArgs)
        RaiseEvent PropertyChanged(Me, e)
    End Sub

    Private m_ip As String
    Private m_status As String

End Class
Public Class TrulyObservableCollection(Of T As INotifyPropertyChanged)
    Inherits ObservableCollection(Of T)

    Protected Overrides Sub InsertItem(index As Integer, item As T)
        MyBase.InsertItem(index, item)
        Me.HookItem(item)
    End Sub

    Protected Overrides Sub SetItem(index As Integer, newItem As T)
        Dim oldItem As T = Me.Items(index)
        MyBase.SetItem(index, newItem)
        Me.UnhookItem(oldItem)
        Me.HookItem(newItem)
    End Sub

    Protected Overrides Sub RemoveItem(index As Integer)
        Dim item As T = Me.Items(index)
        MyBase.RemoveItem(index)
        Me.UnhookItem(item)
    End Sub

    Protected Overrides Sub ClearItems()
        For Each item As T In Me.Items
            Me.UnhookItem(item)
        Next
        MyBase.ClearItems()
    End Sub

    Private Sub HookItem(item As T)
        If (Not item Is Nothing) Then AddHandler item.PropertyChanged, AddressOf Me.HandleItemPropertyChanged
    End Sub

    Private Sub UnhookItem(item As T)
        If (Not item Is Nothing) Then RemoveHandler item.PropertyChanged, AddressOf Me.HandleItemPropertyChanged
    End Sub

    Private Sub HandleItemPropertyChanged(sender As Object, e As PropertyChangedEventArgs)
        Me.OnCollectionChanged(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))
    End Sub

End Class