2
\$\begingroup\$

What would be the preferred way of handling game screens in WPF (conforming to MVVM)? I'm not asking about game states but the actual mechanics of presenting various screens.

Do I implement screens as user controls? Do I collapse and show controls or dynamically add and remove controls from main window? How do I handle transitions (MenuToOptions, OptionsToMenu, GameToOptions, et cetera)?

\$\endgroup\$
2
  • \$\begingroup\$ How are you displaying things in WPF? Are you using a Canvas (or whatever it's called) or are you using some kind of integration with XNA? \$\endgroup\$ Feb 19, 2011 at 18:58
  • \$\begingroup\$ I'm not using XNA, just WPF. It's custom controls mostly, but that isn't the issue. I just wan't to know if there are any guidelines as to how to manage screens in WPF. \$\endgroup\$
    – Goran
    Feb 19, 2011 at 19:35

3 Answers 3

1
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ I thought pages would be the correct choice. But I do find your templates idea interesting - will try it out. \$\endgroup\$
    – Goran
    Feb 23, 2012 at 8:10
2
\$\begingroup\$

Honestly I hate the built-in page system in WPF. It is clearly designed for web-browsing.

I recommend just creating a grid and dynamically adding/removing (or changing visibility) your elements (CustomControls or UserControls) for your MainWindow. Because each of these are just WPF elements within the same grid you can blend their opacity for smooth transitions or transform them with animations set through styles with animations. This also makes it easier for you to handled shared resources (frame / page system children are sandboxed basically) as well as easier to handle cross page functionality because you can always RelativeSource your way back to the MainWindow and then Path your way down into a different child element.

For example (Animation just thrown together probably doesn't work)

<Grid>
    <MainGame Visbility="{Binding Path=Mode, Converter=EqualsParamToVisible, ConverterParam={x:Static GameModeEnum.MainGame}}"/>
    <StartScreen Visbility="{Binding Path=Mode, Converter=EqualsParamToVisible, ConverterParam={x:Static GameModeEnum.StartScreen}}"/>

    <!-- AFAIK WPF draws these in code order if no z order specified -->
    <Rectangle x:Name="GrayOutGameWhenPaused" Visibility="{Binding ElementName=PART_PauseMenu, Path=Visibility}" Fill="#7F000000"/>
    <PauseMenu Margin="40, 30" x:Name="PART_PauseMenu">
        <PauseMenu.Style>
           <Style TargetType="{x:Type PauseMenu}">
               <Style.Triggers>
                   <DataTrigger Binding="{Binding Path=Paused}" Value="True">
                       <DataTrigger.EnterActions>
                           <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="PART_PauseMenu" Storyboard.TargetProperty="RenderTransform.RotateTransform.Angle" From="0" To="360"  Duration="0:0:0.5" RepeatBehavior="4x" />
                                </Storyboard>
                           </BeginStoryboard>
                       </DataTrigger.EnterActions/>
                   </DataTrigger>
               </Style.Triggers>
           </Style>
        <PauseMenu.Style/>
    </PauseMenu>
</Grid>

It kind of depends on what kind of interface and what game you are trying to build. A simple game with a static interface like Tetris would be super easy to build in WPF. A complex user interface with a high performance game underneath - say a first person shooter through a Direct3d surface - might be to much to do like this.

\$\endgroup\$
0
0
\$\begingroup\$

I don't have a big WPF experience, but as I'm working in a game using it, I've had some ideas that we're using:

There is a MainWindow, something to hold all the aplications. Then, for each screen of the game, I create a page that will hold the necessary information (both graphic and logical). That way, one only need's to access the MainWindow in order to perform page changes, create constructor with parameters to pages and etc.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .