4

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")?
Cameron
  • 2,574
  • 22
  • 37
Derrick Moeller
  • 4,808
  • 2
  • 22
  • 48
  • 1
    if you want open dialogs you can do it like : http://stackoverflow.com/questions/3801681/good-or-bad-practice-for-dialogs-in-wpf-with-mvvm – blindmeis Apr 11 '14 at 12:34

3 Answers3

5

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.

Lennart
  • 9,657
  • 16
  • 68
  • 84
Geert van Horrik
  • 5,689
  • 1
  • 18
  • 32
  • Hi. So I'm trying to go with this solution but I have to ask. Will this work with a solution where the Views and ViewModels are in separate projects? I've been trying to go with the documentation so far but I haven't had much joy. – Offer Apr 17 '16 at 16:59
  • Yep, shouldn't make a difference, you just have to make sure the locators and naming conventions are correctly set up. – Geert van Horrik Apr 18 '16 at 11:26
2

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.

Ken Hung
  • 752
  • 5
  • 13
1

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

StepUp
  • 36,391
  • 15
  • 88
  • 148