避免MVVM中更胖的视图模型

时间:2014-03-17 09:58:00

标签: wpf mvvm prism-4

我正在研究一个遵循MVVM模式的WPF应用程序。尽管将验证转移到服务中,我最终会得到一个运行多行代码的胖视图模型(在我的情况下接近1000行)。 我在这里添加了viewmodel的界面。我将一些集合暴露为组合并基于组合选择,我必须对其他组合执行验证/调用服务/应用过滤

public interface ISampleViewModel         {
        ObservableCollection<InstrumentDto> Collection1 { get; set; }
        ObservableCollection<TenderViewConfigDetailViewModel> Collection2 { get; set; }
        ObservableCollection<TenderViewConfigDetailViewModel> Collection3 { get; set; }
        ObservableCollection<TenderViewConfigDetailViewModel> Collection4 { get; set; }
        ObservableCollection<TenderViewConfigDetailViewModel> Collection5 { get; set; }
        TenderViewConfigDetailViewModel SelectedViewConfigDetail { get; set; }
        int SelectedTenderViewIndex { get; set; }
        int SelectedInstrumentsViewIndex { get; set; }
        SortableCollection<TenderViewToInstrumentViewModel> CurrentInstruments { get; set; }
        TenderViewToInstrumentViewModel SelectedInstrumentForTenderView { get; set; }
        InstrumentDto SelectedInstrument { get; set; }
        bool IsAllInstrumentsFocused { get; set; }
        ICommand ApplyChangesCommand { get; }
        ICommand AddTenderPanelViewCommand { get; }
        ICommand DeleteTenderPanelViewCommand { get; }
        ICommand ModifyTenderViewVisiblityCommand { get; }
        ICommand AddInstrumentsToPanelViewCommand { get; }
        ICommand DeleteInstrumentsFromPanelViewCommand { get; }
        ICommand MoveUpTenderListViewCommand { get; }
        ICommand MoveDownTenderListViewCommand { get; }
        ICommand MoveUpInstrumentsCommand { get; }
        ICommand MoveDownInstrumentsCommand { get; }
        bool IsValidModel { get; }
        void PublishTenderViewConfigChanges(TenderViewConfigDetailViewModel viewModel,EventActionType actionType);
    }

上述功能使我的viewmodel变得更加庞大。我该如何避免避免呢?我不能想到将功能分解为更小的控件,因为它们依赖于它们?我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:2)

如果您已存储在可以在单独的类中隔离的ViewModel属性中,则最好将它们移到单独的Model。大量属性非常重要ViewModel,对于您应创建Model的每种类型的属性。虽然在这种情况下存在一些争论,但我认为如果在ViewModel中将链接到多个Models,则没有任何错误。在这个主题上你可以看到这个答案:

In MVVM, is every ViewModel coupled to just one Model?

使用单独模型的示例:

<强> Model

public class MainMenuModel : NotificationObject // Here also implemented INotifyPropertyChanged interface
{
    private bool _buttonIsEnabled = true;

    public bool ButtonIsEnabled
    {
        get
        {
            return _buttonIsEnabled;
        }

        set
        {
            _buttonIsEnabled = value;
            NotifyPropertyChanged("ButtonIsEnabled");
        }
    }     
}

<强> ViewModel

public class MainMenuViewModel
{
    private MainMenuModel _mainMenuModel = null;

    public MainMenuModel MainMenuModel
    {
        get
        {
            return _mainMenuModel;
        }

        set
        {
            _mainMenuModel = value;
        }
    }

    ...

    public MainMenuViewModel() 
    {
        MainMenuModel = new MainMenuModel();
    }
}

<强> View

<Button IsEnabled="{Binding Path=MainMenuModel.ButtonIsEnabled}" ... />

唯一可以留在ViewModel,命令和IDataErrorInfo接口实现的一面,尽管IDataErrorInfo的实现也可以移到Model的一边{1}}。

此外,如果Command的实现占用大量空间,您可以创建可以称为Helper的单独函数/过程并放置在合适的类中。接下来,在Command中没有编写整个实现,有必要参考这个方法。

例如:

private ICommand _findCommand = null;

public ICommand FindCommand
{
    get
    {
        if (_findCommand == null)
        {
            _findCommand = new RelayCommand(param => this.Find(), null);
        }

        return _findCommand;
    }
}

private void Find()
{
    // Here instead of writing large code, 
    // moving find logic to separate static class

    SomeHelper.FindPerson(MainModel.SearchName);
}

因此,在这种情况下,Command是ViewModel中调用方法的包装器。