1

I have some academic question here. I read this question WPF MVVM Get Parent from VIEW MODEL and concluded that ViewModel should not opens any windows itself. So I use Messenger now to send message to ViewModel's Window and Window opens other window - NewWindow. It works fine, but what if NewWindow does something and get some Result has to be passed in MainWindow for further actions? More detailed:

  1. NewWindow opened by button click in Window (OpenNewWindowCommand) and made some calculations.
  2. After calculations NewWindow got some Result (does't matter what exactly is it) and rise a corresponding event - GotSomeResult, where event arg is Result.
  3. This Result has to be passed in MainWindow to further processing, so I bind event handler to GotSomeResult event.

Below you can see all required code to illustrate this scenario.

MainWindow code-behind:

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainWindowViewModel();

    Messenger.Default.Register<NewWindowMessage>(this, OpenNewWindow);
}

private void OpenNewWindow(NewWindowMessage message)
{
    var newWindow = new NewWindow();
    var newWindowViewModel = (NewWindowViewModel) message.Target;        
    newWindowViewModel.GotSomeResult += ((MetaWindowViewModel)DataContext).ProcessResult;

    newWindow.Owner = this;
    newWindow.DataContext = newWindowViewModel;
    newWindow.ShowDialog();

}

MainWindow ViewModel:

public void OpenNewWindowCommand()
{
    Messenger.Default.Send(new NewWindowMessage(this, new NewWindowViewModel("OpenWindow"), String.Empty));
}

public void ProcessResult(Object someResult)
{
     // Any actions with result
}

newWindowViewModel.GotSomeResult += ((MetaWindowViewModel)DataContext).ProcessResult; --- this string seems problem for me. Is it correct to get access to public method of ViewModel right in theView? Does it violent MVVM pattern?

Community
  • 1
  • 1
monstr
  • 1,680
  • 1
  • 25
  • 44
  • thats the way i do dialogs in mvvm http://stackoverflow.com/questions/3801681/good-or-bad-practice-for-dialogs-in-wpf-with-mvvm – blindmeis Jun 17 '14 at 12:21

1 Answers1

2

Why don't you hook the handler to GotSomeResult at the VM level, ie :

public void OpenNewWindowCommand()
{
    var newWindowViewModel = new NewWindowMessage(this, new NewWindowViewModel("OpenWindow"), String.Empty)
    newWindowViewModel.GotSomeResult += this.ProcessResult;

    Messenger.Default.Send();
}

It removes the references to your ViewModel in your codebehind (which indeed should be avoided):

private void OpenNewWindow(NewWindowMessage message)
{
    var newWindow = new NewWindow();

    newWindow.Owner = this;
    newWindow.DataContext = message.Target;
    newWindow.ShowDialog();
}
franssu
  • 2,422
  • 1
  • 20
  • 29
  • Hmm, you are right, that is better solution. I supposed having references to `ViewModel` in `View` - bad idea. You confirmed my suspicions. But how about that standart string? DataContext = new MainWindowViewModel(); It is reference to `ViewModel` too. Didn't? – monstr Jun 17 '14 at 12:32
  • It is certainly a reference to `MainWindowViewModel` – franssu Jun 17 '14 at 12:34
  • Then what is wrong with having references to other `ViewModel`s in `View`? And calling methods of those `ViewModel`s? – monstr Jun 17 '14 at 12:36
  • Any reference to anything should be avoided whenever it can be. For the sake of low [coupling](http://en.wikipedia.org/wiki/Coupling_(computer_programming)) – franssu Jun 17 '14 at 12:40
  • If I remove references to `ViewModel`s from `MainView` to `MainViewModel`, I will have these references anyway, but just in other place (in `MainViewModel`, not in the `View`). The question is - why should I avoid have references in the `View` rather then in `ViewModel`. Hope my bad `English` pretty good and I explaine clearly. Sry if question seems stupid :) – monstr Jun 17 '14 at 12:48
  • MVVM is composed of 3 layers. `View layer`, `ViewModel layer`, and `Model layer`. The `View layer` doesn't need to have any hard references to the `ViewModel layer`, as the (powerful) binding engine provide runtime resolution and invocation of types and methods. It's important is to keep those layers separated. Any hard reference between the two layers is inherently bad. That doesn't mean that any references between two `ViewModels` inside the `ViewModel layer` is okay, but it can be okay, while a cross-layer V/VM reference is certainly not. – franssu Jun 17 '14 at 12:59