当项目的属性发生变化时,我正试图让ObservableCollection
触发CollectionChanged
事件。我使用了here中的代码来执行此操作但是我在从C#转换为Vb.net时遇到了错误。在任何情况下item_PropertyChanged
都没有被解雇。我在这里缺少什么?
代码:
Imports System.ComponentModel
Imports System.Collections.Specialized
Imports System.Collections.ObjectModel
Class MainWindow
Public Class TrulyObservableCollection(Of T As INotifyPropertyChanged)
Inherits ObservableCollection(Of T)
Public Sub New()
MyBase.New()
AddHandler CollectionChanged, AddressOf TrulyObservableCollection_CollectionChanged
End Sub
Private Sub TrulyObservableCollection_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
If e.NewItems IsNot Nothing Then
For Each item As [Object] In e.NewItems
AddHandler TryCast(item, INotifyPropertyChanged).PropertyChanged, AddressOf item_PropertyChanged
Next
End If
If e.OldItems IsNot Nothing Then
For Each item As [Object] In e.OldItems
RemoveHandler TryCast(item, INotifyPropertyChanged).PropertyChanged, AddressOf item_PropertyChanged
Next
End If
End Sub
Private Sub item_PropertyChanged(sender As Object, e As PropertyChangedEventArgs)
Dim a As New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)
OnCollectionChanged(a)
End Sub
End Class
Public Class edm
Implements INotifyPropertyChanged
Property ip As String
Property status As String
Public Sub New(ip As String, status As String)
Me.ip = ip
Me.status = status
End Sub
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
End Class
Public Property edms As New TrulyObservableCollection(Of edm)
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
DataContext = Me
edms.Add(New edm("192.168.1.111", "On"))
edms.Add(New edm("192.168.1.112", "Off"))
edms.Add(New edm("192.168.1.113", "On"))
End Sub
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
edms.Where(Function(edm) edm.ip = "192.168.1.111").First().status = "Off"
End Sub
End Class
编辑:
Bjørn和Liero都提供了很好的答案,在这种情况下,我发现很难将其标记为正确而不是另一个,所以我选择的理由是,当Bjørn的帖子回答了我提出的问题时,我标记了Liero的答案,因为他的评论引导我找到适用于我的方案的最佳解决方案。
答案 0 :(得分:2)
如果值与支持字段不同,则需要在每个属性的setter中引发属性更改事件。
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
因此,您的edm
课程应该更像这样:
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
而且,正如liero中answer正确指出的那样,您最好覆盖InsertItem
,SetItem
,RemoveItem
和{{1}而不是处理ClearItems
事件。
CollectionChanged
答案 1 :(得分:1)
你是对的,你需要附加每个项目的PropertyChanged事件。但是订阅时你不能依赖于CollectionChanged事件。例如,清除集合时,旧项不在事件参数中。还可以将项目传递给ObservableCollection ctor。
更好的方法是覆盖方法ClearItems
,RemoveItem
,InsertItem
,SetItem
已经有一些实现,例如:
当然我前段时间写过自己的:) 但由于WPF引入了实时整形,我并不需要它:
编辑:不要忘记在属性发生变化时触发propertychanged事件,就像@Bjørn-RogerKringsjå提议的那样。根据评论,您的问题不在于observablecollection,而在于您的类的INotifyPropertyChanged实现