代码之家  ›  专栏  ›  技术社区  ›  Charlie

MVVM层次结构中的更改通知

  •  15
  • Charlie  · 技术社区  · 15 年前

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

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

    然后,我创建了一个更具体的视图模型,它继承了前一个视图模型,其中包含以下属性:

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

    现在,在某些视图类中,我绑定到前面提到的视图模型 Rectangle 财产。一切正常,直到我改变尺寸。什么时候? Size 变化, 矩形 不知道,并且更改不会传播到视图。从那时起 矩形 在儿童班,我不能简单地添加 OnPropertyChanged("Rectangle") 尺寸 设定器。

    现在假设我有很多不同的属性,比如 矩形 ,所有这些都依赖于基类属性,并且没有传播这些更改。我需要一些轻量级和优雅的链接更改通知的方法,最好是一种不需要大量代码并且不强制我使用依赖属性的方法。

    显然,这里有很多丑陋的解决方案——我要找的是干净和聪明的东西。在我看来,这是一个非常常见的情况,在我看来,可能有一个 MVVM友好型 这样做的方式。

    5 回复  |  直到 15 年前
        1
  •  9
  •   Brian Genisio    15 年前

    我最近在博客上提到了这个确切的问题。我包括一个 [DependsUpon("Size")] 具有矩形的属性。我真的很喜欢这种方法,因为它将依赖性知识与创建依赖性的代码保持在一起,而不是相反。

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

        2
  •  4
  •   Thomas daign    15 年前

    我使用乔什史密斯的属性观察器,您可以从他的MVVM基础库获得 http://mvvmfoundation.codeplex.com/ .

    用途:

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

    布赖恩的属性方法也不错。我喜欢PropertyObserver的一点是,我可以执行任意代码;允许我检查可能使我避免提升的条件,或者一起执行其他操作。

        3
  •  3
  •   Josh    15 年前

    您可以简单地重写派生视图模型中的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方法中,它基本上只是查看在发生属性更改时哪些其他属性需要失效。

        4
  •  1
  •   kiwipom    15 年前

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

    在某个地方创建一个singleton messenger对象-主应用程序类总是一个不错的地方。

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

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

    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"));
        }
    }
    

    当然,您可以根据需要为该消息添加任意多的订阅-每个需要将更改通知回视图的属性都有一个订阅…

    希望这有帮助:)

        5
  •  0
  •   ecathell    15 年前

    可能是因为我是一个vb用户,但在矩形代码中,您似乎正在访问私有大小声明,而不是公共大小属性,该属性不会触发OnPropertyChanged事件来警告视图。

    另外,我可能会偏离基准,但矩形不应该是一个实际的对象,而大小是该对象的属性吗?也许这就是你正在做的……一些C方法对我来说仍然是陌生的。