Question

I am working on a WPF application that follows an MVVM pattern. Inspite of moving the validation into services, I am ending up with a fat viewmodels that runs for several lines of code(in my case close to 1000 lines). I have added the interface for the viewmodel here. I got a few collections exposed as combo and based on the combo selection, I have to perform validation/invoke service/apply filtering to other combos

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

The above set of functionality make my viewmodel bulkier. How can I avoid avoid it? I cant think of breaking the functionality into smaller controls as they are dependent? Am I missing something here?

Was it helpful?

Solution

If you have stored in the ViewModel properties that can be isolated in separate classes, it is best to move them to a separate Model. Large number of properties pretty loads ViewModel, for each type of properties you should create your Model. Although on this occasion there is some debate, I believe there is nothing wrong if in the ViewModel will be links to several Models. On this subject you can see this answers:

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

Example of using separate models:

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}" ... />

The only thing that can be left on the side of the ViewModel, it Commands and IDataErrorInfo interface implementation, although implementation of IDataErrorInfo can also be moved to the side of the Model.

Also, if the implementation of Command takes a lot of space, you can create separate function / procedure that can be called such Helper and place in suitable class. Next, in Command did not write the whole implementation, it's necessary refer to this method.

For example:

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

Therefore Command in this case is a wrapper for a call method in ViewModel.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top