没有数据绑定时,将属性从Model更改为View

时间:2013-10-21 10:32:28

标签: wpf vb.net mvvm propertychanged

我知道这已经讨论了很多,但是我还没有能够解决这个问题。

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

1 个答案:

答案 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;