This topic contains the following sections.

This topic gives a brief overview on interoperability with Windows Forms and the Windows Presentation Foundation (WPF).

Interoperability Overview

The namespace DigitalRune.Graphics.Interop provides controls to host an XNA Game inside a Windows Forms or WPF application. The interoperability classes where specifically designed to enable the following scenario:

  • The game can run normally inside the default game window.

  • The user can switch between windowed (desktop) and full-screen mode.

  • From the running game, the user can switch to a game editor which is hosted inside a Windows Forms or WPF application.

  • The game editor allows one or more independent views on the game world. While the game editor is visible, the game can keep running uninterrupted.

That means, the interoperability classes provided by DigitalRune Graphics do not replace the XNA game class. They merely extend the functionality to allow developers to build complex game editors or simulation tools.

Tip

Take a look at the InteropSample, which demonstrates how to run an XNA game inside a Windows Forms or WPF application. The examples shows how to switch the game between windowed mode, fullscreen mode, Windows Forms and a WPF window.

Launching a game editor

The following examples show how to start an external window, such as a game editor, from an XNA game.

Windows Forms

The following examples shows how to open a Windows Form.

C# Copy imageCopy
// Create a new Windows Forms window.
var form = new MyForm() { GraphicsServices = _graphicsManager };

// Make the window visible.
form.Show();

Windows Presentation Foundation (WPF)

The class WpfEnvironment is a helper class that provides an execution environment for a WPF window inside a Windows Forms application (such as the XNA game).

The following examples shows to open a WPF window.

C# Copy imageCopy
// WPF windows need to run on a separate thread. This thread is prepared by 
// the WpfEnvironment class. (Redundant calls of Startup() are no problem.)
WpfEnvironment.Startup(Window.Handle);

// WPF windows must be created and handled on the WPF thread. From the WpfEnvironment 
// class we can get the Dispatcher. We can use it to execute actions on the WPF thread. 
WpfEnvironment.Dispatcher.Invoke((Action)(() =>
{
  var window = new MyWindow() { GraphicsServices = _graphicsManager };
  window.Show();
}));

Presenting 3D Graphics inside a Window

A control that shows a 3D scene of the XNA game is called a presentation target. The namespace includes a FormsPresentationTarget (for Windows Forms) and a ElementPresentationTarget (for WPF). These controls can be added inside a Windows Forms or WPF window.

Presentation targets need to be registered in the graphics service (see property PresentationTargets). Care needs to be taken to avoid any cross-thread issues - particularly in WPF. The following examples shows how to register and unregister presentation targets of a WPF window.

XAML Copy imageCopy
<Window x:Class="MyApplication.MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dr="http://schemas.digitalrune.com/windows">
  <Grid>
      <!--  A WPF presentation target into which XNA graphics can be rendered:  -->
      <dr:ElementPresentationTarget x:Name="PresentationTarget" />
    </Grid>
  </Grid>
</Window>
C# Copy imageCopy
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using DigitalRune.Graphics;
using DigitalRune.Graphics.Interop;

namespace InteropSample
{
  // A WPF window with a presentation target for 3D graphics.
  public partial class MyWindow
  {
    public IGraphicsService GraphicsService { get; set; }

    public WpfWindow()
    {
      InitializeComponent();
      Loaded += OnLoaded;
    }

    private void OnLoaded(object sender, RoutedEventArgs eventArgs)
    {
      // Register render targets.
      WpfEnvironment.Form.BeginInvoke((Action)(() =>
      {
        if (GraphicsService != null)
          GraphicsService.PresentationTargets.Add(PresentationTarget);
      }));
    }

    protected override void OnClosing(CancelEventArgs eventArgs)
    {
      // Unregister render targets.
      WpfEnvironment.Form.BeginInvoke((Action)(() =>
      {
        if (GraphicsService != null)
          GraphicsService.PresentationTargets.Remove(PresentationTarget);
      }));

      base.OnClosing(eventArgs);
    }
  }
}

The graphics service can render a scene into the registered presentation targets. This is usually done in the Draw-method of the XNA game.

C# Copy imageCopy
protected override void Draw(GameTime gameTime)
{
  // Update graphics service.
  _graphicsManager.Update(gameTime.ElapsedGameTime);

  foreach (var presentationTarget in _graphicsManager.PresentationTargets)
  {
    // Prepare scene (camera, etc.) for presentation target.
    ...

    // Render scene into presentation target.
    _graphicsManager.Render(presentationTarget);
  }

  // Render scene into back buffer.
  _graphicsManager.Render(false);

  base.Draw(gameTime);
}

See Also