Derrick Moeller
Derrick Moeller

Reputation: 4950

Opening new window from ViewModel

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.

Upvotes: 4

Views: 4283

Answers (3)

Geert van Horrik
Geert van Horrik

Reputation: 5724

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.

Upvotes: 5

Ken Hung
Ken Hung

Reputation: 782

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.

Upvotes: 2

StepUp
StepUp

Reputation: 38094

If you want to see good example, see how this works in the ViewModel (EmailClient) sample application of the WPF Application Framework (WAF).

Upvotes: 1

Related Questions