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).