There are two ways I can think to do this easily
The first would be to use a Popup
instead of a new Window
. For example, I often put properties in my ViewModel
for PopupContent
and IsPopupVisible
, and set those values anytime I want to display my Popup
control. For example, a ShowAboutPopup
relay command might run something like this:
void ShowAboutPopup()
{
PopupContent = new AboutViewModel();
IsPopupVisible = true;
}
You can display it using a Popup
object, or a custom UserControl
. I prefer to use my own custom Popup UserControl, which will usually end up looking like this:
<Window>
<Canvas x:Name="RootPanel">
<SomePanel>
<!-- Regular content goes here -->
</SomePanel>
<local:PopupPanel Content="{Binding PopupContent}"
local:PopupPanel.IsPopupVisible="{Binding IsPopupVisible}"
local:PopupPanel.PopupParent="{Binding ElementName=RootPanel}" />
</Canvas>
</Window>
The PopupContent
property is a ViewModel
(such as an AboutViewModel
), and DataTemplates
are used to tell WPF to draw specific ViewModels
with specific Views
<Window.Resources>
<DataTemplate DataType="{x:Type local:AboutViewModel}">
<local:AboutView />
</DataTemplate>
</Window.Resources>
The other method is to have some kind of ApplicationViewModel
that runs on startup, and is responsible for the overall application state, which includes which window(s) are open.
Typically I prefer to have a single ApplicationView
that contains a ContentControl
to display the current page
<Window>
<ContentControl Content="{Binding CurrentViewModel}" />
</Window>
however it can also be used to manage multiple windows. If you do use it to manage multiple Window
objects, be warned that this will not be a pure ViewModel
because it will need to access some View-specific objects, and referencing UI objects it not something a ViewModel
should do. For example, it may subscribe to receive ShowWindow
messages, and upon receiving those messages it would create the specified View and show it, and possibly hide the current window as well.
Personally, I try to avoid multiple windows as much as possible. My usual method is to have a single View that contains consistent application objects for any page, and a ContentControl
containing dynamic content that changes. I have an example using this navigation style on my blog if you're interested