Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to Easily Host WPF Control inside Windows Form Application

0.00/5 (No votes)
31 Mar 2014 1  
This article demonstrates an easy way to host WPF control inside Windows Form application.

Introduction

In this article, I will demonstrate how to create a "grid like" combo-box and host it inside a Windows Form application.

Background

WinForms applications have limited user interface (UI) abilities compared with WPF. Does this justify transposing the whole application from WinForms to WPF?

In my opinion, not always. Sometimes you can easily give a “facelift” to your application using WPF controls.

As a side note, if you want to upgrade your Windows Form application, you should consider HTML5 and not WPF. While I personally love working with WPF, upgrading to HTML5 will get you a multi-platform web application at a lower cost, especially if you do it automatically using transposition tools. I've done many of these projects and it is certainly easier than re-writing it to WPF.

However, in the meantime, you can use “hosting” - embedding a WPF control inside your Windows Form application in order to take advantage of the richness (and easiness - after some practice) of WPF within a Windows Form application. Also, creating complicated controls in WPF usually takes less time than creating them in Windows Form.

MSDN has an article about "Hosting a WPF composite control in Windows Forms" but I believe it to be too complicated.

What I present here is an easy example of hosting a WPF control inside Windows Forms application in a way that is simple to follow and implement, and is also more suitable from the perspective of project architecture.

Stages

  1. Creating the WPF "Grid like" combo-box
  2. Creating the Windows form hosting Control
  3. Adding the control to Windows Form application

1. Creating WPF "Grid like" Combo-box

Let us start by writing the WPF control.

Our aim is a simple control of a combo-box containing "grid-like" properties of a “customer”:

XAML

<UserControl x:Class="WindowsFormsControlLibrary1.ComboBoxWithGrid"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="250">
    <Grid>
        <ComboBox x:Name="comboBox"
        Margin="4"
        ItemsSource="{Binding Customers}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Label BorderThickness="1,1,0,1" 
                        BorderBrush="Black" Content="{Binding Path=Name}" />
                        <Label BorderThickness="1,1,0,1" 
                        BorderBrush="Black" Content="{Binding Path=Address}" />
                        <Label BorderThickness="1" 
                        BorderBrush="Black" Content="{Binding Path=TelephoneNumber}" />
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>
</UserControl>  

As we can see in the XAML above, we define a combo-box with customer as an item source. The combo-box has an item template for presenting the customer details in a "grid-like" style:

In WPF, it is easily done using three labels and binding their context into the "Customer" class properties.

Customer Class

    public class Customer
    {
        public string Name { get; set; }
 
        public string Address { get; set; }
 
        public string TelephoneNumber { get; set; }
    } 

Then, all we have left to do is to write the WPF control code behind:

    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class ComboBoxWithGrid : UserControl
    {
        public ComboBoxWithGrid()
        {
            InitializeComponent();
            SelectedIndex = 0;
 
            this.DataContext = this;
        }
 
        public int SelectedIndex 
        {
            get
            {
               return comboBox.SelectedIndex;
            }
            set
            {
                comboBox.SelectedIndex = value;
            }
        } 
        public List<Customer> Customers { get; set; }
    } 

As we can see, the code behind is very simple, setting the DataContext as this, exposing the Customers list, for outside & for the XAML data binding, and also exposing the select index for outside only.

2. Creating the Windows Form Hosting Control

This step is actually easier. I am creating a simple class that inherits from System.Windows.Forms.Integration.ElementHost:

    [Designer("System.Windows.Forms.Design.ControlDesigner, System.Design")]
    [DesignerSerializer("System.ComponentModel.Design.Serialization.TypeCodeDomSerializer , System.Design", "System.ComponentModel.Design.Serialization.CodeDomSerializer, System.Design")]
    public class ComboBoxWithGrid_WinformsHost : System.Windows.Forms.Integration.ElementHost
    {
        protected ComboBoxWithGrid m_WPFComboBoxWithGrid = new ComboBoxWithGrid();

        public ComboBoxWithGrid_WinformsHost()
        {
            base.Child = m_WPFComboBoxWithGrid;     
        }     

        public int SelectedIndex
        {
            get
            {
                return m_WPFComboBoxWithGrid.SelectedIndex;
            }
            set
            {
                m_WPFComboBoxWithGrid.SelectedIndex = value;
            }
        }
  
        public List<Customer> Customers
        {
            get
            {
                return m_WPFComboBoxWithGrid.Customers;
            }
            set
            {
                m_WPFComboBoxWithGrid.Customers = value;
            }
        }
    } 

This class inherits from ElementHost object that holds the WPF control as a child.

Please notice that I have override back to default the Designer Smart-Tag and the DesignerSerializer attributes in order to prevent an override of the Child element by the Designer.

3. Adding the Control to Windows Form Application

First, we just need to drag & drop the new control inside our Windows Form:

And then, connect the customer list to the control by code-behind:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            var customers = new List<Customer>();
 
            for (int i = 0; i < 10; i++)
            {
                customers.Add(new Customer() { Name = "Name" + i, 
                Address = "Address" + i, TelephoneNumber = "TelephoneNumber" + i });
            }
 
            this.comboBoxWithGrid_WinformsHost1.Customers = customers;
 
            this.comboBoxWithGrid_WinformsHost1.SelectedIndex = 6;
        }
    }  

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here