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
已经有一些实现,例如:
编辑:不要忘记在属性更改时触发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