Walkthrough: Hosting a Third-Party Windows Forms Control in a WPF Application

This walkthrough shows you how to use the Windows Presentation Foundation (WPF) Designer for Visual Studio to host a Windows Forms third-party vendor control in a WPF application. For more information about Windows Forms and WPF interoperability, see Migration and Interoperability.

In this walkthrough, you will use a MonthCalendar control to represent a third-party vendor control. You create a UserControl type which has an instance of the MonthCalendar control in its Controls collection. The UserControl type exposes a Date property and implements custom logic to define the MonthCalendar control's behavior. In the WPF application, a TextBlock element is bound to the Date property.

In this walkthrough, you perform the following tasks:

  • Create the WPF project.

  • Create a Windows Forms user control to encapsulate the vendor control.

  • Host the Windows Forms user control in a WPF application.

The following illustration shows how your application will appear.

Hosted Windows Forms Control

Note

The dialog boxes and menu commands you see might differ from those described in Help depending on your active settings or edition. To change your settings, choose Import and Export Settings on the Tools menu. For more information, see Visual Studio Settings.

Prerequisites

You need the following components to complete this walkthrough:

  • Visual Studio 2008.

Creating the WPF Project

The first step is to create the WPF project for the host application.

To create the project

  1. Create a new WPF Application project in Visual Basic or Visual C# named HostingMonthCalendar. For more information, see How to: Create a New WPF Application Project.

    Window1.xaml opens in the WPF Designer.

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

Creating the Windows Forms Composite Control

This procedure shows how to create a composite control by deriving a type from the UserControl class.

To create the Windows Forms composite control

  1. Add a new Windows Forms Control Library project in Visual Basic or Visual C# named VendorControlLibrary to the solution. For more information, see How to: Add and Remove Solution Items.

    UserControl1 opens in the Windows Forms Designer

  2. In Solution Explorer, right-click the UserControl1 file, and select Rename.

  3. Change the name of the control to VendorControl. When you are asked if you want to rename all references, click Yes.

  4. Open VendorControl in the Windows Forms Designer.

  5. On the design surface, select the VendorControl.

  6. In the Properties window, set the value of the Size property to 200,200.

  7. From the Toolbox, double-click the MonthCalendar control.

    A MonthCalendar control appears on the design surface.

  8. In the Properties window, set the following properties for the MonthCalendar control.

    Property

    Value

    Margin

    0,0,0,0

    ShowToday

    False

  9. In the Windows Forms Designer, set the size of VendorControl to match the size of the MonthCalendar control.

  10. Select the MonthCalendar control.

  11. In the Properties window, click the Events tab and double-click the DateChanged event.

    The VendorControl file opens in the Code Editor, and an event handler for the DateChanged event is added.

  12. Replace the existing code with the following code. This code defines a Date property and some logic for restricting the MonthCalendar control's date range properties, SelectionStart and SelectionEnd, to the same value as TodayDate. This code also implements the INotifyPropertyChanged interface, which is used in WPF data binding.

    Imports System
    Imports System.Collections.Generic
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Data
    Imports System.Linq
    Imports System.Text
    Imports System.Windows.Forms
    
    Public Class VendorControl
        Inherits UserControl
        Implements INotifyPropertyChanged
    
        <Browsable(True)> _
        Public Property [Date]() As String 
            Get 
                Return Me.MonthCalendar1.TodayDate.ToShortDateString()
            End Get 
    
            Set(ByVal value As String)
                If value <> Me.MonthCalendar1.TodayDate.ToShortDateString() Then 
                    Dim newDate As DateTime = DateTime.Parse(value)
                    Me.SetDate(newDate)
                    Me.NotifyPropertyChanged("Date")
                End If 
            End Set 
        End Property 
    
    
        Private Sub monthCalendar1_DateChanged( _
            ByVal sender As Object, ByVal e As DateRangeEventArgs) _
        Handles MonthCalendar1.DateChanged
            Me.SetDate(e.Start)
            Me.NotifyPropertyChanged("Date")
    
        End Sub 
    
    
        Private Sub SetDate(ByVal [date] As DateTime)
            Me.MonthCalendar1.TodayDate = [date]
            Me.MonthCalendar1.SelectionStart = [date]
            Me.MonthCalendar1.SelectionEnd = [date]
    
        End Sub
    
    #Region "INotifyPropertyChanged Implementation" 
    
        Public Event PropertyChanged As PropertyChangedEventHandler _
            Implements INotifyPropertyChanged.PropertyChanged
    
        Private Sub NotifyPropertyChanged(ByVal info As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
        End Sub
    
    #End Region
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace VendorControlLibrary
    {
        public partial class VendorControl : UserControl, INotifyPropertyChanged
        {
            public VendorControl()
            {
                InitializeComponent();
            }
    
            [Browsable(true)]
            public string Date
            {
                get
                {
                    return this.monthCalendar1.TodayDate.ToShortDateString();
                }
    
                set
                {
                    if (value != this.monthCalendar1.TodayDate.ToShortDateString())
                    {
                        DateTime newDate = DateTime.Parse(value);
                        this.SetDate(newDate);
                        this.OnPropertyChanged("Date");
                    }
                }
            }
    
            private void monthCalendar1_DateChanged(object sender, DateRangeEventArgs e)
            {
                this.SetDate(e.Start);
                this.OnPropertyChanged("Date");
            }
    
            private void SetDate(DateTime date)
            {
                this.monthCalendar1.TodayDate = date;
                this.monthCalendar1.SelectionStart = date;
                this.monthCalendar1.SelectionEnd = date;
            }
    
            #region INotifyPropertyChanged Implementation
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void OnPropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            #endregion
        }
    }
    
  13. On the Build menu, select Build Solution to build the solution.

Hosting the Windows Forms Control in WPF

You use the WindowsFormsHost element to host VendorControl in a WPF application.

To host the Windows Forms control in WPF

  1. In the HostingMonthCalendar project of Solution Explorer, add a reference to the VendorControlLibrary project. For more information, see How to: Add or Remove References in Visual Studio (Visual Basic).

  2. Open Window1.xaml in the WPF Designer.

  3. In XAML view, replace the existing markup with the following markup. This XAML maps the VendorControlLibrary namespace, creates a WindowsFormsHost element, and binds a TextBlock element to the Date property on VendorControl.

    <Window x:Class="HostingMonthCalendar.Window1"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:v="clr-namespace:VendorControlLibrary;assembly=VendorControlLibrary"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition />
            </Grid.RowDefinitions>
    
            <WindowsFormsHost Name="Host" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
                <v:VendorControl Date="2/2/03" />
            </WindowsFormsHost>
    
            <TextBlock Grid.Row="1" 
                       Text="{Binding ElementName=Host, Path=Child.Date, Mode=OneWay, UpdateSourceTrigger=PropertyChanged }" 
                       HorizontalAlignment="Stretch" 
                       VerticalAlignment="Center" 
                       TextAlignment="Center" 
                       TextDecorations="None" 
                       FontSize="24" />
        </Grid>
    </Window>
    
  4. From the Debug menu, select Start Debugging.

  5. Click the MonthCalendar control to change the current date. The WPF TextBlock element updates to display the selected date.

Next Steps

  • If your control will be widely used in a WPF environment, you can derive your own class from WindowsFormsHost and expose the Date property. This enables other WPF controls to bind directly to the Date property, without using the Path=Child.Date syntax.

  • You can also host WPF controls in Windows Forms. For more information, see Using Windows Presentation Foundation Controls.

See Also

Tasks

Walkthrough: Hosting a Windows Forms Control in Windows Presentation Foundation

Reference

WindowsFormsHost

ElementHost

Other Resources

Working with Controls in the WPF Designer

Migration and Interoperability

Change History

Date

History

Reason

September 2010

Added missing step.

Customer feedback.