Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening new window from ViewModel

Tags:

c#

mvvm

wpf

How should I be opening new windows? I'm currently doing the following.

EventArgs:

public class GenericViewRequestedEventArgs : EventArgs
{
    public GenericViewModel ViewModel { get; private set; }

    public GenericViewRequestedEventArgs(GenericViewModel viewModel)
    {
        ViewModel = viewModel;
    }
}

ViewModel:

public class MainWindowViewModel : ViewModelBase
{
    private RelayCommand _viewSpecificCommand;

    public ICommand ViewSpecificCommand
    {
        get
        {
            if (_viewSpecificCommand == null)
                _viewSpecificCommand = new RelayCommand(x => viewSpecific());

            return _viewSpecificCommand;
        }
    }

    public EventHandler<GenericViewRequestedEventArgs> GenericViewRequested;

    private void RaiseGenericViewRequested(GenericViewModel viewModel)
    {
        var handler = GenericViewRequested;
        if (handler != null)
            handler(this, new GenericViewRequestedEventArgs(viewModel));
    }

    private void viewSpecific()
    {
        RaiseGenericViewRequested(_specificViewModel);
    }
}

View:

public partial class MainWindow : Window
{
    private void OnGenericViewRequested(object sender, GenericViewRequestedEventArgs e)
    {
        GenericWindow window = new GenericWindow(e.ViewModel);
        window.ShowDialog();
    }
}

This does work, but it seems like a lot of code and I end up with code behind in my view any ways.

  • What's the logic behind sending the command to the viewmodel at all?
  • Is it just to optionally use the predicate(if so why not bind to Enabled) and possibly avoid exposing additional viewmodels as properties?
  • Should I be attaching simple event handlers in the XAML(e.g. Click="btnViewSpecific_Click")?
like image 400
Derrick Moeller Avatar asked Feb 13 '23 06:02

Derrick Moeller


2 Answers

It depends on how "strict" you want to follow the MVVM pattern. This is just one of the basic pitfalls of MVVM and you can solve it depending on your preferences. One way is to simply use the code-behind, but then how will you handle application-wide commands, keyboard shortcuts, etc? It is a bit too short-sighted IMHO.

I think you should at least consider using existing frameworks that have solved these issues for you years ago and will provide you with a solid base for your application.

For example, Catel has a IUIVisualizerService that can show windows based on a view model. The major advantage is that you can push data into the view model and respond to the result as a service. Another nice advantage is that you can mock the IUIVisualizerService so you can test the reacting code on different results provided by the dialog.

** Disclaimer **

I am the developer of Catel, so I have explained the Catel way here. If anyone else wants to comment on other frameworks, feel free to comment or create a new answer.

like image 129
Geert van Horrik Avatar answered Feb 16 '23 03:02

Geert van Horrik


Yes, there are a lot of additional codes for MVVM. Building a command that independent of Views is usually for unit testing, such that the command and ViewModel can be unit tested without involving UI components.

However, if the "command" is just opening a window, it is not worth to create a command, and unit test the command to see if the GenericViewRequested is really fired(you can even check if the correct _specificViewModel is returned). The codes are far more complicated and just little value is added. Just open the window in View's button click event handler and it is fine.

like image 43
Ken Hung Avatar answered Feb 16 '23 04:02

Ken Hung