MonoGame in WPF

Since every sign points to the death of XNA, we’ve slowly started transitioning to a complete MonoGame setup. With just a couple of minor adjustments, the game runs great using MonoGame.

One big obstacle we encountered was porting our tools. Prior to using MonoGame, we we’re using Nick Gravelyn’s blog post WPF Hosting for XNA Game Studio 4.0 (http://blogs.msdn.com/b/nicgrave/archive/2011/03/25/wpf-hosting-for-xna-game-studio-4-0.aspx) which worked tremendously well during the production of Wizorb minus not being able to render over the window. (no context menues)

Paris Editor running a GLControl

At the time of writing, MonoGame on Windows (not 8) uses OpenTK. So we we’re looking for a quick way to setup a window in WPF. OpenTK has GLControl, a Windows forms UserControl. While I cringe at the thought of mixing WPF with Windows Forms, we really needed something quick and dirty. Since this was for our tools and we don’t plan to package them with our games, we didn’t really care to find the cleanest solution. So maybe I should have really named this post “MonoGame in Windows Forms” as this is somewhat of a workaround.

You can start off by looking at the code. http://code.jfmajor.com/GLGraphicsDevice.cs

You’ll notice most of Nick Gravelyn’s code is unchanged. What we had to change was how the control was getting rendered. The Paint event doesn’t get triggered unless the UserControl gets invalidated. In our case, that can be pretty much never. So we added a Timer that gets triggered every 1/60th of a second and invalidates our UserControl.

To use this, you’ll need to add a WindowsFormsHost in your XAML.

<wf:WindowsFormsHost x:Name="m_oglForm" Grid.Row="0"/>

When you create your Window, you’ll want to set your GLGraphicsDevice to be a child of this WindowsFormsHost.

GLGraphicsDevice l_graphicsDevice = new GLGraphicsDevice();
m_oglForm.Child = l_graphicsDevice;

You’ll also want to add a hook to RenderXna to do your rendering.

RenderXna += Render;
That pretty much sums it up.
Alternatively, you could also use Nick’s older method of rendering to a RenderTarget2d and then writing this data to a WriteableBitmap. (http://blogs.msdn.com/b/nicgrave/archive/2010/07/25/rendering-with-xna-framework-4-0-inside-of-a-wpf-application.aspx) However, this is very expensive on the CPU and it rendered our tools nearly unusable on older computers.