Skip to content

Hosting a WPF Control in WinForms

In this article I will show you how to host a WPF Control inside WinForms.

Introduction

Hosting a WPF Control in your Windows Form is quite easy and takes just a few steps. Therefore, Microsoft provides the class ElementHost to embed the WPF Control in your Windows Form. For demonstration I will add a standard WPF Button to a Windows Form and rise an WPF Popup Dialog when the button is pushed. You can host a custom WPF Controls in the same way.

Adding some assembly references

You need to add a reference to WindowsFormsIntegration.dll in your Windows Forms project. This assembly contains the definition of ElementHost.

Furthermore, you need to add a reference to the project or assembly which contains the definition of the WPF Control you want to embed. In this example we will use the WPF Button Control. Therefore, we will need to reference the PresentationFramework.dll assembly.

Finally, you need to add a reference to PresentationCore.dll to add WPF support.

Adding the Button Control

To add a WPF Control to a Windows Form you need to set the WPF Control as child of a ElementHost instance and add the ElementHost to a WinForms Panel.

using System; using System.Windows.Forms; using System.Windows.Forms.Integration; namespace HostingWpfInsideWinForms { public partial class HostingForm : Form { public HostingForm() { InitializeComponent(); } private void Form_Load(object sender, EventArgs e) { var elementHost = new ElementHost(); elementHost.Dock = DockStyle.Fill; Controls.Add(elementHost); var wpfButton = new System.Windows.Controls.Button(); wpfButton.Content = "Push me!"; //If you are hosting a WPF User Control don't forget to call InitializeComponent() elementHost.Child = wpfButton; } } }
Code language: C# (cs)

Adding an event handler for Button Clicked event

using System; using System.Windows.Forms; using System.Windows.Forms.Integration; namespace HostingWpfInsideWinForms { public partial class HostingForm : Form { public HostingForm() { InitializeComponent(); } private void Form_Load(object sender, EventArgs e) { var elementHost = new ElementHost(); elementHost.Dock = DockStyle.Fill; Controls.Add(elementHost); var wpfButton = new System.Windows.Controls.Button(); wpfButton.Content = "Push me!"; wpfButton.Click += WpfButton_Click; //If you are hosting a WPF User Control don't forget to call InitializeComponent() elementHost.Child = wpfButton; } private void WpfButton_Click(object sender, System.Windows.RoutedEventArgs e) { MessageBox.Show("WPF Button clicked!"); } } }
Code language: C# (cs)

Attaching a Command Handler for Button Click

You can handle commands in the same way as in WPF. The only difference is that you need to add the command in code. I will use the DelegateCommand provided by prism, so I added the NuGet Package Prism.WPF.

using Prism.Commands; using System; using System.Windows.Forms; using System.Windows.Forms.Integration; namespace HostingWpfInsideWinForms { public partial class HostingForm : Form { public HostingForm() { InitializeComponent(); } private void Form_Load(object sender, EventArgs e) { var elementHost = new ElementHost(); elementHost.Dock = DockStyle.Fill; Controls.Add(elementHost); var wpfButton = new System.Windows.Controls.Button(); wpfButton.Content = "Push me!"; wpfButton.Command = new DelegateCommand(new Action(ButtonClickedCommad)); //If you are hosting a WPF User Control don't forget to call InitializeComponent() elementHost.Child = wpfButton; } private void ButtonClickedCommad() { MessageBox.Show("WPF Button Command Handled!"); } } }
Code language: PHP (php)

Adding a Binding to the WPF Button Content Dependeny Property

It is also possible to add Bindings to WPF Dependency Properties. In this example I will add a Binding for the Dependency Property ‘Content’ of the WPF Button Control. We only need to do a few steps to establish a Binding:

  • The class where the source property resides (HostingForm) needs to implement the INotifyPropertyChanged interface so that the WPF engine gets notified when the property value changed.
  • Adding a property for the button caption (ButtonText)
  • Establish the binding between the ‘ButtonText’ property and the ‘Content’ property of the WPF Button
using Prism.Commands; using System; using System.ComponentModel; using System.Windows.Forms; using System.Windows.Forms.Integration; namespace HostingWpfInsideWinForms { public partial class HostingForm : Form, INotifyPropertyChanged { private string _buttonText = "Initial Text"; public event PropertyChangedEventHandler PropertyChanged; public HostingForm() { InitializeComponent(); } private void Form_Load(object sender, EventArgs e) { var elementHost = new ElementHost(); elementHost.Dock = DockStyle.Fill; Controls.Add(elementHost); var wpfButton = new System.Windows.Controls.Button(); wpfButton.Content = "Push me!"; wpfButton.Command = new DelegateCommand(new Action(ButtonClickedCommad)); //If you are hosting a WPF User Control don't forget to call InitializeComponent() // Bind the ButtonText property (source) from this Form to the Content Dependency Property of the WPF Button System.Windows.Data.Binding contentBinding = new System.Windows.Data.Binding("ButtonText"); contentBinding.Source = this; wpfButton.SetBinding(System.Windows.Controls.Button.ContentProperty, contentBinding); elementHost.Child = wpfButton; } public string ButtonText { get => _buttonText; set { _buttonText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ButtonText")); } } private void ButtonClickedCommad() { ButtonText = "WPF Button Command Handled!"; } } }
Code language: C# (cs)

In the example above the initial button text will be changed when the button is clicked.

Copyright (c) by Thomas Kemp, 2021