2

I have a WPF application that uses the pattern and I need to show a dialog from my principal view model.

I have a secondary view with its view model, and I think that I have two options to create the dialog.

OPTION 1

In the principal view model I can do the following:

  1. Create the view of the dialog
  2. Create de view model of the dialog
  3. Assign the view model to the view
  4. ShowDialog

OPTION 2

In the principal view model:

  1. Create the view model of the dialog

In the constructor of the view model of the dialog:

  1. Create the view of the dialog
  2. Assign the view model to the view. In this case is assign "this"
  3. ShowDialog

I know that in MVVM the view model has to know nothing about the view, but in the second option, in practice, how the view model has not any property that link to the view, only is create an showed in the constructor, in the final state the view model does not know nothing about the view.

However, I think that the code in the principal view is clearer, because I only need to create the view model, only one line of code, instead of the option 1 that need 4 lines (create the view, cretate the view model, assign the view model to the view and show the dialog).

Am I wrong in thinking that the second option is not a bad idea if I want to follow the pattern?

Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Álvaro García
  • 18,114
  • 30
  • 102
  • 193

3 Answers3

1

Well as in most cases, there are several approaches to implement a solution.

For larger applications with several dialogs, windows or pages the best approach would be a service e.g. IDialogHandler. Which is given to the VMs via c_tor. You can find an example in this post.
Big advantage is the decoupling which makes the VMs easy to test, because they have no references to the views.

For smaller applications with let's say 2 or 3 different dialogs the following approach would also be proper.

public class DialogView : Window
{
    // a method to create easily a dialog
    public static void ShowDialog(DialogViewModelBase dialogVm)
    {
        var dialog = new DialogView { DataContext = dialogVm };
        dialog.ShowDialog(); // pls note, that this will create a modal dialog
    }
}

So DialogView.ShowDialog(...) could be called from everywhere. But here the VMs have a references to the views.
This is similar to your OPTION 1, well ok the step order is not the same, but it's close enough.

Community
  • 1
  • 1
DHN
  • 4,807
  • 3
  • 31
  • 45
1

i do this for dialogs in wpf

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);

... do anything with the dialog result...
Community
  • 1
  • 1
blindmeis
  • 22,175
  • 7
  • 55
  • 74
1

Whatever way you chose there's one trouble.
Frankly speaking it relates not only to dialog but to all windows. And in MVVM this can become a real pain. At least for our team when we use both WinForms and WPF.

Most of the developers forget about parent-child relationships of the windows.
Concerning dialog windows this causes somewhat poor UX: it is possible for the dialog to go beneath the main window which is unresponsive because of the shown dialog. (you can easily repoduce it).

So, in MVVM you need somehow set the parent. And what is important here is tha View is not necessary a Window.

Here how we do it.
We preffered ViewModel-first approach. But we do not inject View in VM. We pass IViewService which is repsonsible for View instantiation, parent-child relationships and listening for some events.
Think about how yor VM can stop its View from closing when user clicks cross at the upper right corner.

Pavel Voronin
  • 13,503
  • 7
  • 71
  • 137