C# – The best approach to create new window in WPF using MVVM

cmvvmnetwpf

In the neighbour post: How should the ViewModel close the form?
I've posted my vision how to close windows with MVVM usage. And now I have a question: how to open them.

I have a main window (main view). If user clicks on the "Show" button then "Demo" window (modal dialog) should be displayed. What is a preferable way to create and open windows using MVVM pattern? I see two general approaches:

The 1st one (probably the simplest). Event handler "ShowButton_Click" should be implemented in the code behind of the main window in way like this:

        private void ModifyButton_Click(object sender, RoutedEventArgs e)
        {
            ShowWindow wnd = new ShowWindow(anyKindOfData);
            bool? res = wnd.ShowDialog();
            if (res != null && res.Value)
            {
                //  ... store changes if neecssary
            }
        }
  1. If we "Show" button state should be changed (enabled/disabled) we will need to add logic that will manage button state;
  2. The source code is very similar to "old-style" WinForms and MFC sources – I not sure if this is good or bad, please advise.
  3. Something else that I've missed?

Another approach:

In the MainWindowViewModel we will implement "ShowCommand" property that will return ICommand interface of the command. Comman in turn:

  • will raise "ShowDialogEvent";
  • will manage button state.

This approach will be more suitable for the MVVM but will require additional coding: ViewModel class can't "show dialog" so MainWindowViewModel will only raise "ShowDialogEvent", the MainWindowView we will need to add event handler in its MainWindow_Loaded method, something like this:

((MainWindowViewModel)DataContext).ShowDialogEvent += ShowDialog;

(ShowDialog – similar to the 'ModifyButton_Click' method.)

So my questions are:
1. Do you see any other approach?
2. Do you think one of the listed is good or bad? (why?)

Any other thoughts are welcome.

Thanks.

Best Answer

Some MVVM frameworks (e.g. MVVM Light) make use of the Mediator pattern. So to open a new Window (or create any View) some View-specific code will subscribe to messages from the mediator and the ViewModel will send those messages.

Like this:

Subsription

Messenger.Default.Register<DialogMessage>(this, ProcessDialogMessage);
...
private void ProcessDialogMessage(DialogMessage message)
{
     // Instantiate new view depending on the message details
}

In ViewModel

Messenger.Default.Send(new DialogMessage(...));

I prefer to do the subscription in a singleton class, which "lives" as long as the UI part of the application does. To sum up: ViewModel passes messages like "I need to create a view" and the UI listens to those messages and acts on them.

There's no "ideal" approach though, for sure.