1

I am trying to make my WPF application decoupled and thus I did something like:

  • Project of the View.

  • Project of the ViewModel.

In the mainwindow I did binding between a button to an OpenChildWindowCommand which is located in the ViewModel DLL.

OpenChildWindowCommand inherits from ICommand and execute a call to OpenChildWindow method in the MainViewModel.

Now the problem is that the ViewModel does not know about the ChildWindow because it is a different DLL.

What I'm asking is: what is the best way doing it - that the child window will be opened?

Maybe some kind of messaging between them.

kayess
  • 3,384
  • 9
  • 28
  • 45
user1902346
  • 799
  • 1
  • 12
  • 21
  • 1
    take a look at http://stackoverflow.com/questions/3801681/good-or-bad-practice-for-dialogs-in-wpf-with-mvvm – blindmeis Nov 23 '16 at 10:01
  • See [Open File Dialog in MVVM](https://stackoverflow.com/a/64861760/3141792) and [MVVM DialogService alternatives](https://stackoverflow.com/a/57131723/3141792). – BionicCode Nov 29 '21 at 01:03

3 Answers3

1

First of all I congratulate you on physically separating your views from your viewmodels - keeping them in the same assembly leads many people into taking shortcuts that they shouldn't.

With your button binding I would suggest that you put the command code in the code behind of the view. It is an interaction with the view that is causing the childwindow to be opened, so there is fundamentally no reason why the command code needs to be in the viewmodel. Your code will look something like this:

public ICommand OpenChildWindowCommand
{
    get 
    {
        return new DelegateCommand<object>(ExecuteOpenChildWindowCommand, CanOpenChildWindowCommandExecute);
    }
}

private void ExecuteOpenChildWindowCommand(object context)
{
    ...code to open the child window...
}

private void CanOpenChildWindowCommandExecute(object context)
{
    return true;
}

(The DelegateCommand<T> is from Microsoft's PRISM library). Your XAML will look something like this:

<Button x:Name="MyButtonName" 
        Command="{Binding OpenChildWindowCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 
        />

What I suggest you do then is start using a dialog service - this is some dialog related code that is abstracted into a standalone helper style service. Going into the details of a dialog service will make this answer a bit long, so here's some helpful links to get you started:

If you combine your new dialog service with using an IoC container then you can have some very nice decoupled MVVM and test friendly code that looks like this:

public class MyMainWindow
{
    private IDialogService dialogService;

    public MyMainWindow(IUnityContainer container)
    {
        dialogService = container.Resolve<IDialogService>();
    }

    private void ExecuteOpenChildWindowCommand(object context)
    {
        var dlg = _dialogService.Show<IMyDialogWindow>();
    }
}

(You initialise the container and register the interface to concrete class mappings early on in application startup).

Community
  • 1
  • 1
slugster
  • 49,403
  • 14
  • 95
  • 145
0

Use EventAggregator for communication between two modules.

Vijay
  • 663
  • 4
  • 15
0

I'm not sure if you are utilizing any specific framework in your application, but even if you aren't, take a cue from Microsoft's Prism framework and the MSDN Prism documentation. Specifically, look at the advanced section User Interaction Patterns:

Basically, you simply create an interaction request on your view model, where the result of the interaction is passed through a callback delegate.

Typically, these are simple substitutions of a MessageBox, but I have used this pattern for more complex scenarios such as age verification, confirmation box (yes/no), and even entire screens that ask for name and address.

There isn't a real simple answer to your question, because it really depends on what you are doing... but in the past I used MEF to load modules, and the EventAggregator/Container to get the content of Modal Windows.

Really, at the end your primary ViewModel uses the interface to start the interaction, other components of the framework create the popup, load the content, and complete the interaction. All the while, the viewmodels have no idea about windows or popups or any of that, just other viewmodels and payload classes. This means that everything can be unit tested without any issue.

myermian
  • 31,823
  • 24
  • 123
  • 215