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

使用MVVM模式时,与属性更改相关的代码应该放在setter或事件中吗?

  •  4
  • si618  · 技术社区  · 14 年前

    寻找有关在何处放置依赖于属性更改的代码的指导。

    例如,我有一个视图模型,用于保存应用程序设置的状态

    public SettingsViewModel(ISettingsRepository settings)
    {
        _settings = settings;
        // ...
    }
    

    对于设置属性的每次更改,我们都必须将此更改保留到存储库中,并且在某些属性上,其他属性会受到影响,因此需要额外的代码。

    我刚开始把这个逻辑添加到setter中

    public ProjectCollection Projects
    {
        get { return _projects; }
        set
        {
            if (_projects == value) return;
            _projects = value;
            RaisePropertyChanged("Projects");
    
            // Extra work needed when collection of projects change
            _settings.SaveProjects(_projects);
            Startable = _projects != null && _projects.Count > 0;
        }
    }
    

    但后来换了个线路 PropertyChanged 事件为 INotifyPropertyChanged 并从属性设置器中删除了附加代码

    public SettingsViewModel(ISettingsRepository settings)
    {
        _settings = settings;
        // ...
        PropertyChanged += onPropertyChanged;
    }
    
    void onPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "Projects":
                _settings.SaveProjects(Projects);
                Startable = Projects != null && Projects.Count > 0;
                break;
            // ...
        }
    }
    
    public ProjectCollection Projects
    {
        get { return _projects; }
        set
        {
            if (_projects == value) return;
            _projects = value;
            RaisePropertyChanged("Projects");
        }
    }
    

    在setter中使用逻辑意味着要编写的代码更少,错误连接错误的属性名的可能性更小(不过,单元测试应该会记住这一点),而且速度会稍快一点,尽管可能无关紧要。

    将逻辑连接到事件上似乎是一种更易于维护的方法,只要方法的名称恰当,就应该更容易遵循代码,这意味着除了设置属性外,setter不做其他工作。我猜,使用上面的例子,它还可能提供更大的灵活性,如果需求发生了变化,从而使另一个事件(如“保存”按钮单击而不是属性更改)发生了持续的更改,那么代码应该更容易更改。

    我很欣赏这是一个主观的问题,但我对MVVM模式是新的(尽管我猜它可能适用于任何设置器逻辑?)所以,在我确定一个方法之前,我要寻找其他的原因。谢谢!

    1 回复  |  直到 13 年前
        1
  •  4
  •   slugster Joey Cai    14 年前

    OnPropertyChanged()