Skip to main content

C# - Using WPF In WinForms [Beginner]


A little while back, we did a tutorial on how to embed WinFoms controls inside of WPF application (you can read all about it here). Today, we are going to flip that on its head - we are going to take a look at how to embed WPF controls inside of a WinForms application.

You might be thinking to yourself "why would someone want to do that?" A great question, and there are a couple different reasons. First, perhaps you have an application already written in WinForms, but you want to move to WPF. Instead of rewriting the entire thing from scratch (which might be a large amount of work, and might be time/cost prohibitive), you can rewrite portions of the application as time allows or when you need to redo a particular section anyway.

Another reason would be if there is a area of your app that would be easy to do in WPF (maybe because of the animation features, or the composibility) while in WinForms it would be difficult.

So what do we need to do to enable this integration? Well, first off, we need to add a reference to the Visual Studio project. You do this by right clicking on "References" in the Solution Explorer and choosing "Add Reference":

Add Reference Context Menu

Once you have the dialog up, you want to scroll to the bottom on the .NET tab and choose the "WindowsFormsIntegration" component, and hit OK:

Add Reference Dialog

At this point, you probably want to create the WPF user control that you want to add to your app. If its already written, you can add it through the Add Existing Item menu option, and if you need to write one, you can choose "Add New Item" and under WPF choose "User Control". In my case I want to create a new one, and I'm going to name it "MyWPFControl":

Add New Item Dialog

So my made-up reason why I want a WPF control in my WinForms app is that I want a custom combo box - or really a combo box with some custom items. While this is doable in WinForms, it is hard. Downright annoying in many ways. In WPF, though, its really easy, since you can put whatever you want in a ComboBoxItem. In this case, my user control consists of a combo box with three items - a circle, a triangle, and a rectangle:
<UserControl x:Class="WPFInWinForms.MyWPFControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
  <Grid>
    <ComboBox>
      <ComboBoxItem Margin="2">
        <Ellipse Width="20" Height="20" Stroke="Black" />
      </ComboBoxItem>
      <ComboBoxItem Margin="2">
        <Path Stroke="Black" Data="M 0,0 L 20,0 L 10,20 Z" />
      </ComboBoxItem>
      <ComboBoxItem Margin="2">
        <Rectangle Stroke="Black" Width="20" Height="20" />
      </ComboBoxItem>
    </ComboBox>
  </Grid>
</UserControl>
 
OK, now that we have the control we want to add, how do we add it? Well, there are two ways of going about this - one is through the designer, and the other is by adding the control manually in code. We are fist going to take a look at the designer way of doing things.

When we added that reference earlier, one of the things it did was give us access to a control called ElementHost. This control is for WPF in WinForms what the WindowsFormsHost was for WinForms in WPF. In the designer, you can find this control in the Toolbox underneath "WPF Interoperability":

WPF Interoperability Toolbox Section

So once you drag an ElementHost onto your form, the designer makes things really easy for you. You just click on the little arrow on the upper right of the ElementHost and you get a couple options. The one we care about is the combobox for "Select Hosted Content". When you click this, you get to choose what WPF control you want to host in the ElementHost:

Element Host Options

Once you do that, well, thats it. You can run the app, and the WPF control will show up exactly where you put it:

WPF in WinForms

Doing all of this in code is also quite easy. In fact, I'll just throw all the code up here in one block:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Integration;

namespace WPFInWinForms
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();

      ElementHost elhost = new ElementHost();
      elhost.Size = new Size(110, 60);
      elhost.Location = new Point(45,35);

      MyWPFControl wpfctl = new MyWPFControl();
      elhost.Child = wpfctl;

      this.Controls.Add(elhost);
    }
  }
}
 
So the first thing needed is that last using statement. The ElementHost lives in that namespace, so we add a using statement for it. After that, we just create a new ElementHost, and set its normal WinForms properties. Then we create an instance of the wpf control we want, and add that as the child for the ElementHost. Finally, we add the ElementHost as a child to the current form - and we are all done!

So that is it for using WPF controls inside of Windows Forms. You can download the little sample app from here if you would like to play with the code yourself. 

Source Files:

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >(); ...

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as...

C# WPF Tutorial - Implementing IScrollInfo [Advanced]

The ScrollViewer in WPF is pretty handy (and quite flexible) - especially when compared to what you had to work with in WinForms ( ScrollableControl ). 98% of the time, I can make the ScrollViewer do what I need it to for the given situation. Those other 2 percent, though, can get kind of hairy. Fortunately, WPF provides the IScrollInfo interface - which is what we will be talking about today. So what is IScrollInfo ? Well, it is a way to take over the logic behind scrolling, while still maintaining the look and feel of the standard ScrollViewer . Now, first off, why in the world would we want to do that? To answer that question, I'm going to take a an example from a tutorial that is over a year old now - Creating a Custom Panel Control . In that tutorial, we created our own custom WPF panel (that animated!). One of the issues with that panel though (and the WPF WrapPanel in general) is that you have to disable the horizontal scrollbar if you put the panel in a ScrollV...