Windows Presentation Foundation (WPF) provides a rich environment for creating applications. However, when you have a substantial investment in Windows Forms code, it can be more effective to reuse at least some of that code in your WPF application rather than to rewrite it from scratch. The most common scenario is when you have existing custom Windows Forms controls. In some cases, you might not even have access to the source code for these controls. WPF provides a straightforward procedure for hosting such controls in a WPF application. For example, you can use WPF for most of your programming while hosting your specialized System.Windows.Forms.DataGridView controls.

This walkthrough steps you through an application that hosts a composite Windows Forms control on a WPF page. This general procedure can be extended to more complex applications and controls.

The walkthrough is divided into two sections. The first section briefly describes the implementation of the Windows Forms control. The second section discusses in detail how to host the control in a WPF application, receive events from the control, and access some of the control's properties.

The Windows Forms control used in this example is a simple data-entry form. This form takes the user's name and address and then uses a custom event to return that information to the host. The following illustration shows the rendered control.

The Windows Forms control

Creating the Project

To start the project:

Launch Microsoft Visual Studio, and open the New Project dialog box.

Select C# Projects with the Windows Forms Control Library template.

Name the new project MyControls, and click OK to create the project. The default project contains a single control named UserControl1.

Change the name of UserControl1 to MyControl1.

Your project should have references to the following system DLLs. If any of these DLLs are not included by default, add them to the project.

Add two System.Windows.Forms.Button controls labeled OK and Cancel. In the example, the button names are btnOK and btnCancel, respectively.

Implementing the Supporting Code

Open the form's code view. The control returns the collected data to its host by raising the custom OnButtonClick event. The data is contained in the event argument object. The following code example shows the event and delegate declaration. Add this code to the code file, below the designer-generated code.

When the user clicks the OK or Cancel button, the Control.Click event handlers create a MyControlEventArgs object that contains the data and raises the OnButtonClick event. The only difference between the two handlers is the event argument's IsOK property. This property enables the host to determine which button was clicked. It is set to true for the OK button, and false for the Cancel button. The following code example shows the two button handlers. Add this code to your class, placing it below the event and delegate declaration shown in the first code example in this section.

The WPF host application uses the WindowsFormsHost control to host MyControl1. The application handles the OnButtonClick event to receive the data from the control. It also has a collection of option buttons that enable you to change some of the control's properties from the WPF page. The following illustration shows the finished application.

The complete application, showing the control embedded in the Windows Presentation Foundation page

Creating the Project

To start the project:

Open Visual Studio, and select New Project.

Select the WPF Browser Application template.

Name the project WpfHost, and click OK to open the project.

You will also need to add a reference to the DLL that contains MyControl1. The simplest way to add the reference is as follows.

Right-click the project name in Solution Explorer, and launch the Add Reference dialog box.

Click the Browse tab, and browse to the Windows Form control's output folder. For this sample, this folder is MyControls\bin\Debug.

In Solution Explorer, add a reference to the WindowsFormsIntegration assembly, which is named WindowsFormsIntegration.dll.

Implementing the Basic Layout

The user interface (UI) of the host application is implemented in Page1.xaml. This file contains Extensible Application Markup Language (XAML) markup that defines the page layout, and hosts the Windows Forms control. The page is divided into three regions:

The Control Properties panel, which contains a collection of option buttons that you can use to modify various properties of the hosted control.

The Data from Control panel, which contains several TextBlock elements that display the data returned from the hosted control.

The hosted control itself.

The basic layout code is shown in the following code example. The markup code that is needed to host MyControl1 is omitted from this example, but will be discussed later. Replace the code in Page1.xaml with the following.

The first StackPanel element contains several sets of RadioButton controls that enable you to modify various default properties of the hosted control. That is followed by a WindowsFormsHost element, which hosts MyControl1. The final StackPanel element contains several TextBlock elements that display the data that is returned by the hosted control. The ordering of the elements and the Dock and Height attribute settings embed the hosted control into the page with no gaps or distortion.

Hosting the Control

The following edited version of the previous code example focuses on the elements that are needed to host MyControl1.

The xmlns namespace mapping attribute creates a reference to the MyControls namespace that contains the hosted control. This mapping enables you to represent MyControl1 in XAML as <mcl:MyControl1>.

Two elements in the code example handle the hosting:

WindowsFormsHost represents the WindowsFormsHost element that enables you to host a Windows Forms control on a WPF page.

mcl:MyControl1, which represents MyControl1, is added to the WindowsFormsHost element's child collection. As a result, this Windows Forms control is rendered as part of the WPF page, and you can communicate with the control from the page.

Implementing the Code-Behind File

The code-behind file, Page1.xaml.cs, contains the procedural code that implements the functionality of the UI discussed in the preceding section. The primary tasks are:

Attaching an event handler to MyControl1's OnButtonClick event.

Modifying various properties of MyControl1, based on how the collection of option buttons are set.

Displaying the data collected by the control.

Initializing the Application

The initialization code is contained in an event handler for the page's Loaded event and attaches an event handler to the control's OnButtonClick event. Copy the following code into the Page1 class in Page1.xaml.cs.

Because the XAML code discussed previously added MyControl1 to the WindowsFormsHost element's child element collection, you can cast the WindowsFormsHost element's Child to get the reference to MyControl1. You can then use that reference to attach an event handler to OnButtonClick.

In addition to providing a reference to the control itself, WindowsFormsHost exposes a number of the control's properties, which you can manipulate from the page. The initialization code assigns those values to private global variables for later use in the application.

Handling the OnButtonClick Event

MyControl1 raises the OnButtonClick event when the user clicks either of the control's buttons. Add the following code to your Page1 class.

The data in the text boxes is packed into the MyControlEventArgs object. If the user clicks the OK button, the event handler extracts the data and displays it in the panel below MyControl1.

Modifying the Control’s Properties

The WindowsFormsHost element exposes several of the hosted control's default properties. As a result, you can change the appearance of the control to match the style of your page more closely. The sets of option buttons in the left panel enable the user to modify several color and font properties. Each set of buttons has a handler for the Click event, which detects the user's option button selections and changes the corresponding property on the control. Copy the following code to your Page1 class. You can now compile and run the application.