2

我知道这已经被讨论了很多,但我无法让它发挥作用。

我在 WPF 中有一个视图 - ViewModel - 模型。我需要传递模型中的属性已更改的信息。我需要最终在视图中处理信息。请注意,这里没有从 View 到 ViewModel 的数据绑定。

ViewModel我有一组模型对象:

Public Property Items as ObservableCollection(Of Item)

模型是:

Public Class Item
    Public Property Name as String
End Class

我想要做的是在 ViewModel 中的集合“Items”中的任何项目中更改属性“Name”时运行的 View 代码隐藏(见下文)中运行一个过程。

查看

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(如下),但看起来在此派生类中覆盖事件存在一些问题。不知道“受保护的阴影事件 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
4

1 回答 1

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 >>>

我的扩展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;
于 2013-10-21T11:26:55.767 回答