You have several options, and it all comes down to what works for your specific use case. The easiest option is probably to use a Page
for each of your screens, then use the Navigate() method to switch pages. This has the advantage that is functions much like a browser (and, in fact, there is UI with back/forward buttons just like a browser that you can optionally use). If your application is more akin to a web application this can be very easy to control and extend.
Another option is to simply add and remove elements from the window manually in code behind, however I do not recommend this except as a last resort. You're almost always using WPF incorrectly if you're manually manipulating controls using code instead of using WPF's features.
Another method would be to put all your custom control containers in the window from the beginning, but have them all have the Visibility.Collapsed
state. You can then simply have any number of controls display based on your current application state (although make sure you're doing this with bindings rather than code behind, for the same reason mentioned above.)
Lastly the best option after the Page
navigation is the best WPF way: use templates. Simply put your controls in data templates and then the proper controls will be displayed upon setting your data context! Here's an example (assuming my:
is mapped to your application's namespace)
<Window.Resources>
<DataTemplate DataType="{x:Type my:TitleInformationViewModel}">
<my:TitleScreenPage/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:GameLevelViewModel}">
<my:GameRenderCanvas/>
</DataTemplate>
</Window.Resources>
<DockPanel>
<ContentControl Content="{Binding}"/>
</DockPanel>
Now, you simply set the DataContext
of your window to a view model object depending on what state your game is in an what you want to display. Since a blank {Binding}
binds directly to the DataContext
object, WPF will then search for any templates to use to display that object whenever the DataContext
changes. If the object you set the DataContext
to is a TitleInformationViewModel
object, ContentControl
will use the first template listed there and display your TitleScreenPage
control. If instead it's a GameLevelViewModel
object, it will instead display the GameRenderCanvas
control.
This is much closer to the WPF way than manually adding/removing controls and much cleaner than invisible controls (those controls will still be hooked up and listening to their bindings regardless if they're displayed, which is not really desirable.) This or Page
navigation is your best bets. The Navigation service is handy because you can navigate to any arbitrary page, whereas using DataTemplates requires you to declare all your templates for a window before using any of them.