我知道这已经讨论了很多,但是我还没有能够解决这个问题。
我在WPF中有一个View - ViewModel - Model。 我需要传递Model中的属性已更改的信息。我最终需要在View中处理这些信息。 请注意,View to ViewModel中有无数据绑定。
在 ViewModel 中我有一组模型对象:
Public Property Items as ObservableCollection(Of Item)
模型是:
Public Class Item
Public Property Name as String
End Class
我想要做的是在View代码中运行一个过程(见下文),该过程在ViewModel中“Items”集合中的任何项目中更改属性“Name”时运行。 / p>
查看:
Private Sub NameWasChanged()
'do something to UI...
'Item that was changed must be known here as must the new value for the "Name" property
End Sub
更新1>>>
为了响应您的自定义类,我尝试将其转换为VB.NET(下面),但看起来在此派生类中覆盖Event时存在一些问题。不知道“Protected Shadows Event PropertyChanged”是否是正确的方法。我得到item.PropertyChanged说“PropertyChanged不是T的事件” 你能帮我解决这个问题吗?否则我得到了概念/想法。
Public Class BaseCollection(Of T)
Inherits ObservableCollection(Of T)
Implements INotifyPropertyChanged
Protected currentItem As T
Public Sub New(collection As IEnumerable(Of T))
Me.New()
For Each item As T In collection
Add(item)
Next
End Sub
Public Sub New(collection As ObservableCollection(Of T))
Me.New(TryCast(collection, IEnumerable(Of T)))
End Sub
Public Sub New(ParamArray collection As T())
Me.New(TryCast(collection, IEnumerable(Of T)))
End Sub
Public Sub New()
MyBase.New()
End Sub
Public Shadows Sub Add(item As T)
AddHandler item.PropertyChanged, AddressOf Item_PropertyChanged
MyBase.Add(item)
End Sub
Public Overridable Shadows Sub Add(collection As IEnumerable(Of T))
For Each item As T In collection
Add(item)
Next
End Sub
Public Overridable Shadows Sub Add(ParamArray items As T())
Add(TryCast(items, IEnumerable(Of T)))
End Sub
Protected Overrides Sub InsertItem(index As Integer, item As T)
If item IsNot Nothing Then
AddHandler item.PropertyChanged, AddressOf Item_PropertyChanged
MyBase.InsertItem(index, item)
End If
End Sub
Protected Overrides Sub ClearItems()
For Each item As T In Me
RemoveHandler item.PropertyChanged, AddressOf Item_PropertyChanged
Next
MyBase.ClearItems()
End Sub
Public Shadows Function Remove(item As T) As Boolean
If item Is Nothing Then
Return False
End If
RemoveHandler item.PropertyChanged, AddressOf Item_PropertyChanged
Return MyBase.Remove(item)
End Function
Public Shadows Sub RemoveAt(index As Integer)
Dim item As T = Me(index)
If item IsNot Nothing Then
RemoveHandler item.PropertyChanged, AddressOf Item_PropertyChanged
End If
MyBase.RemoveAt(index)
End Sub
Private Sub Item_PropertyChanged(sender As Object, e As PropertyChangedEventArgs)
NotifyPropertyChanged(e.PropertyName)
End Sub
#Region "INotifyPropertyChanged Members"
Protected Shadows Event PropertyChanged As PropertyChangedEventHandler
Protected Overridable Sub NotifyPropertyChanged(ParamArray propertyNames As String())
For Each propertyName As String In propertyNames
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
Next
End Sub
#End Region
End Class
答案 0 :(得分:2)
如果模型类正确实现了INotifyPropertyChanged
接口,则另一个类可以通过将处理程序附加到INotifyPropertyChanged.PropertyChanged
事件来侦听属性更改:
YourObject.PropertyChanged += YourObject_PropertyChanged;
...
Private Sub YourObject_PropertyChanged(sender As Object, e As PropertyChangedEventArgs)
If InlineAssignHelper(e.PropertyName, "Name") Then
' Do something with the new Name value here
End If
End Sub
更新>>>
如果您想要监控Items
集合属性中每个项目的属性更改,那么您需要将处理程序附加到每个项目......您可以执行以下操作:
For Each item As Item In Items
item.Propertychanged += Item_PropertyChanged
Next
或者将它们添加到Items
:
For Each item As Item In OtherCollection
item.Propertychanged += Item_PropertyChanged
Items.Add(item)
Next
当我需要这样做时,我扩展ObservableCollection<T>
类并覆盖Add
方法以附加处理程序(并从构造函数中调用它们)并覆盖Remove
方法删除处理程序。
更新2&gt;&gt;&gt;
我的扩展ObservableCollection<T>
课程太长了,不能在这里展示,但是为了让你开始,这里有一些......我只是希望我没有删除太多而且一切仍然有效。 ..不管怎样,我想你会明白这个想法:
public class BaseCollection<T> : ObservableCollection<T>, INotifyPropertyChanged
where T : class, INotifyPropertyChanged
{
public BaseCollection(IEnumerable<T> collection) : this()
{
foreach (T item in collection) Add(item);
}
public BaseCollection(ObservableCollection<T> collection) : this(collection as IEnumerable<T>) { }
public BaseCollection(params T[] collection) : this(collection as IEnumerable<T>) { }
public BaseCollection() : base() { }
public new void Add(T item)
{
item.PropertyChanged += Item_PropertyChanged;
base.Add(item);
}
public virtual void Add(IEnumerable<T> collection)
{
foreach (T item in collection) Add(item);
}
public virtual void Add(params T[] items)
{
Add(items as IEnumerable<T>);
}
protected override void InsertItem(int index, T item)
{
if (item != null)
{
item.PropertyChanged += Item_PropertyChanged;
base.InsertItem(index, item);
}
}
protected override void ClearItems()
{
foreach (T item in this) item.PropertyChanged -= Item_PropertyChanged;
base.ClearItems();
}
public new bool Remove(T item)
{
if (item == null) return false;
item.PropertyChanged -= Item_PropertyChanged;
return base.Remove(item);
}
public new void RemoveAt(int index)
{
T item = this[index];
if (item != null) item.PropertyChanged -= Item_PropertyChanged;
base.RemoveAt(index);
}
private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyPropertyChanged(e.PropertyName);
}
#region INotifyPropertyChanged Members
protected override event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(params string[] propertyNames)
{
if (PropertyChanged != null)
{
foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
有了这个,您只需在集合中添加PropertyChanged
处理程序:
BaseCollection<YourDataType> items = new BaseCollection<YourDataType>();
items.PropertyChanged += Item_PropertyChanged;