Well, if I understand correctly, you want to open a modal dialog not from MainWindowViewModel, but from another ChildViewModel?
Take a look at the MainWindowViewModel constructors of the CodeProject article that you linked:
ViewModel has a constructor with the following signature:
public MainWindowViewModel( IDialogService dialogService, IPersonService personService, Func<IOpenFileDialog> openFileDialogFactory)
This means that to build you need a service that shows modal dialogs, another service (personService), which does not matter here, and a factory for a specific dialog for opening openFileDialogFactory files.
To use the service, which is the main part of the article, a simple ServiceLocator is implemented and a default constructor is defined that uses the ServiceLocator to get service instances that the ViewModel requires:
public MainWindowViewModel() : this( ServiceLocator.Resolve<IDialogService>(), ServiceLocator.Resolve<IPersonService>(), () => ServiceLocator.Resolve<IOpenFileDialog>()) {}
This is possible because the ServiceLocator is static. In addition, you can set the local field for services in the constructor using ServiceLocator. This approach is better because it allows you to install services yourself if you do not want to use ServiceLocator.
You can do the same in your own ChildViewModel.
public ChildViewModel(IDialogService dialogService) { _dialogService = dialogService; }
Create a default constructor that calls the aforementioned constructor with a service instance permitted from ServiceLocator:
public ChildViewModel() : this(ServiceLocator.Resolve<IDialogService>()) {}
Now you can use the service from anywhere in the ChildViewModel, for example:
_dialogService.ShowDialog<WhateverDialog>(this, vmForDialog);
To find the owner window of your view, which is not the view itself, you need to change the FindOwnerWindow method of FindOwnerWindow to find the parent window of the view, rather than expecting the window to look like the view itself. You can use VisualTreeHelper for this:
private Window FindOwnerWindow(object viewModel) { var view = views.SingleOrDefault(v => ReferenceEquals(v.DataContext, viewModel)); if (view == null) { throw new ArgumentException("Viewmodel is not referenced by any registered View."); } DependencyObject owner = view;
You still need to register UserControl by setting the attached property to UserControl:
<UserControl x:Class="ChildView" ... Service:DialogService.IsRegisteredView="True"> ... </UserControl>
As far as I can tell, this works.
Additional Information:
To accomplish the same, I use the PRISM framework, which comes with many features for this decoupling, Inversion of Control (IoC) and dependency injection (DI). Maybe it's worth a look at this for you too.
Hope this helps!
Edited to review the comment.