Hosting WPF controls in a WinForms application
Although I am not really using WinForms a lot, I know that there are situations when a WPF control needs to be somehow plugged in to a WinForms project, especially when you want to bring a custom UI design to an existing app. And although it seems to be a quite interesting task to do, in fact it is quite simple.
To get started, I created a WPF User Control Library project in Visual Studio that will be used as the control sample:
I am going to use it to create a simple reusable control that can be plugged in both WPF and WinForms projects. Once the solution is created, you will see the familiar WPF designer:
Here you can pretty much work on everything you can in a regular WPF project, but the build will represent a DLL rather than an application. I created a sample set of elements to be a part of the user control and the XAML code for my control looks like this:
<Rectangle Height="278" HorizontalAlignment="Left" Margin="9,10,0,0" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="283" Fill="Blue" />
<TextBox Height="41" HorizontalAlignment="Left" Margin="19,22,0,0" Name="textBox1" VerticalAlignment="Top" Width="206" />
<Button Content="Set" Height="41" HorizontalAlignment="Left" Margin="231,22,0,0" Name="button1" VerticalAlignment="Top" Width="48" Click="button1_Click" />
Feel free to insert the same code for experimentation purposes. Visually, the control should resemble this UI structure:
However, the control should perform a specific action, so I am going to edit the event handler for the button. What it will do is change the brush color for the rectangle depending on the user input. The code will looks like this:
Brush brush = null;
brush = new BrushConverter().ConvertFromString(textBox1.Text) as Brush;
rectangle1.Fill = brush;
MessageBox.Show("Brush cannot be generated from the specified string.");
MessageBox.Show("No brush specified.");
NOTE: You can add additional properties and events inside the control. If those have the proper access modifiers set, you will be able to later on access them from your WinForms app.
Now you can build the project and get the output DLL. Once you have the library compiled, switch to your WinForms application.
In a WinForms project, there is the ElementHost control available in the Toolbox:
It allows WPF controls to be embedded in WinForms applications. Note that this only applies to WPF controls, and not full-sized applications (unless you decided to implement a complex control). Place one of these controls on your form and decide whether you want it docked or not. The size matters here, because if ElementHost won’t be of the proper size, the control will simply be cut and some parts of it might not be accessible to the end-user.
I am going to add a reference to the newly created DLL in the host application the same way any other reference is added:
It is a standalone DLL, so you will have to open the Browse tab in the References dialog and point to the DLL that contains the control.
Now, in the Form_Load event for the form use the following code to create an instance of a WPF control and assign it as the ElementHost child:
WPFUserControl.UserControl1 control = new WPFUserControl.UserControl1();
elementHost1.Child = control;
Note that the naming can be different, since it all depends on the project name you used for the control (or if you changed the namespace). When the form loads, you are able to see the WPF control hosted inside the ElementHost:
There is another way to add a WPF user control, also with the help of ElementHost, but this specific way works (at least for me) only in Visual Studio 2008 – for some reason, ElementHost won’t recognize the content correctly in Visual Studio 2010.
You can create (or add) a WPF User Control inside the existing solution. When you have it ready, build the user control project and switch to the WinForms application. In the Toolbox, you will see a new control group specific to your WPF User Control project:
You can simply drag it on the form, and an ElementHost will be automatically created with the Child element set to the WPF control. The effect is the same as for the previous way to host WPF controls.