15

假设在一些抽象的 ViewModel 基类中,我有一个普通的旧属性,如下所示:

public Size Size
{
    get { return _size; }
    set
    {
        _size = value;
        OnPropertyChanged("Size");
    }
}

然后,我创建了一个更具体的 ViewModel,继承自前一个,它包含以下属性:

public Rect Rectangle
{
    get { return new Rect(0, 0, _size.Width, _size.Height); }
}

现在,在某些 View 类中,我绑定到上述 ViewModel 的Rectangle属性。一切正常,直到我改变尺寸。当Size更改时,Rectangle不知道它并且更改不会传播到视图。而且由于Rectangle在子类中,我不能简单地将一个添加OnPropertyChanged("Rectangle")Size设置器中。

现在想象一下,我有许多不同的属性,例如Rectangle,它们都依赖于基类属性,并且这些更改都没有被传播。我需要一些轻量级和优雅的链接更改通知的方式,最好是不需要大量代码并且不会强迫我使用依赖属性的方式。

显然这里有很多丑陋的解决方案——我正在寻找的是干净和聪明的东西。在我看来,这将是一个非常常见的场景,在我看来,可能有一种对MVVM 友好的方式来执行此操作。

4

5 回答 5

9

我最近在博客上讨论了这个确切的问题。我[DependsUpon("Size")]在 Rectangle 中包含一个属性。我真的很喜欢这种方法,因为它将依赖知识与创建依赖的代码一起保存,而不是相反。

看看:http ://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx

于 2010-01-06T13:02:57.000 回答
4

我使用 Josh Smith 的 PropertyObserver,您可以从他的 MVVM Foundation 库中获得它,网址为http://mvvmfoundation.codeplex.com/

用法:

_viewmodel_observer = new PropertyObserver<OtherViewModel>(_OtherViewModel)
   .RegisterHandler(m => m.Size, m => RaisePropertyChanged(Rectangle);

Brian 的属性方法也很好。我喜欢 PropertyObserver 的一件事是我可以执行任意代码;允许我检查可能使我避免加注或一起执行其他操作的条件。

于 2010-01-06T16:48:09.167 回答
3

您可以像这样在派生的 ViewModel 中简单地覆盖 OnPropertyChanged:

protected override void OnPropertyChanged(string propertyName) {
    base.OnPropertyChanged(propertyName);
    if (propertyName == "Size") {
        base.OnPropertyChanged("Rectangle");
    }
}

另一种可能性...不久前,我整理了一个非常不错的 ViewModel 基类,它支持以下属性的属性:

[DependsOn("Size")]
public Rect Rectangle {
    get { new Rect(0,0,Size.Width, Size.Height); }
}

然后 ViewModel 基类在运行时收集这些 DependsOnAttribute,在其 OnPropertyChanged 方法中,它基本上只是查看发生属性更改时需要使哪些其他属性无效。

于 2010-01-06T00:27:56.110 回答
1

一个干净的 MVVM 方法是使用Messenger订阅/通知机制(如 Josh Smith 的MvvmFoundation

在某处创建一个单例 Messenger 对象 - 主 App 类始终是这样做的好地方

public partial class App : Application
{
    private static Messenger _messenger;
    public static Messenger Messenger
    {
        get
        {
            if (_messenger == null)
            {
                _messenger = new Messenger();
            }
            return _messenger;
        }
    }
}

在基类的 Size 设置器中,通知更改:

public Size Size
{
    get { return _size; }
    set
    {
        _size = value;
        OnPropertyChanged("Size");

        App.Messenger.NotifyColleagues("SIZE_CHANGED");
    }
}

现在您可以让继承的 ViewModel 监听这些更改,并根据需要引发 PropertyChanged 事件...

public MyViewModel : MyViewModelBase
{
    public MyViewModel()
    {
        App.Messenger.Register("SIZE_CHANGED", () => OnPropertyChanged("Rectangle"));
    }
}

当然 - 您可以根据需要为此消息添加任意数量的订阅 - 每个需要更改以通知给视图的属性一个...

希望这可以帮助 :)

于 2010-01-06T00:28:32.200 回答
0

也许是因为我是一个 VB 人,但在您的 Rectangle 代码中,您似乎正在访问私有 _size 声明而不是 Public Size 属性,该属性不会触发 OnPropertyChanged 事件以提醒视图。

我也可能不在基地,但 Rectangle 不应该是一个实际的对象,而 Size 是该对象的属性?也许这就是你正在做的......一些 C# 方法对我来说仍然很陌生。

于 2010-01-06T12:42:34.997 回答