Hosting WPF User Control in Windows Forms Application

We can use WPF controls in Winforms applications if we want. In some cases, we can easily design a control as WPF, which would be very problem to make in winforms. That's why we can host as a solution.

Before starting the application, I need to specify, the application I will make in this article will proceed through the dotnet CLI. So, I am not going to use Visual Studio in this tutorial.

First, I will create a sample project. I created one empty folder named ProjectExample. I opened cmd terminal in this directory. 

I am creating a solution file for the project with the following command:

dotnet new sln -n "ProjectSolution"
After that, I'm creating a windows forms application called test:
dotnet new winforms -n test
Now it's time to create a WPF user control class. For this I write the following command:
dotnet new wpfusercontrollib -n "wpfcontrol"
After this process, I need to add both applications to the solution file:
dotnet sln ProjectSolution.sln add ./test/test.csproj
dotnet sln ProjectSolution.sln add ./wpfcontrol/wpfcontrol.csproj
Then I add the reference of the wpf user control to the project named test:
dotnet add test/test.csproj reference wpfcontrol/wpfcontrol.csproj
We have finished the settings on the command line. Open the project named test with any editor or ide. I am using VS Code. 

In order to use the WPF UserControl as a host in Winforms, we must first set the following in the test.csproj file:
<Project Sdk="Microsoft.NET.Sdk">

  <ItemGroup>
    <ProjectReference Include="..\wpfcontrol\wpfcontrol.csproj" />
  </ItemGroup>

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWpf>true</UseWpf>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>
Let's run our project for testing purposes and only a blank form window will appear on the screen.
../test> dotnet run
I added a button to the UserControl1.xaml file:
<UserControl x:Class="wpfcontrol.UserControl1"
             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" 
             xmlns:local="clr-namespace:wpfcontrol"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        
        <Button x:Name="btn1">click the button</Button>
                
    </Grid>
</UserControl>
We need to show this control on winforms. Let's open the Form1.Designer.cs file in the test project. First we need to include the two libraries:
namespace test;
using wpfcontrol;
using System.Windows.Forms.Integration;

partial class Form1
{
	...
Next, we integrate the wpf control into winforms using elementhost:
    ...
    UserControl1 test;
    
    private void InitializeComponent()
    {
        ...
        
        ElementHost elementHost = new ElementHost();

        test = new UserControl1();
        elementHost.Child = test;
        
        this.Controls.Add(elementHost);
        
        ...
It's time to run the project and the result is as expected:
WPF User Control in Winforms
If we want to interact with the button in the UserControl, first of all, a public property named Button is defined in the UserControl1 class:
namespace wpfcontrol
{
    ...
    
    public partial class UserControl1 : UserControl
    {
        public Button Button1 {get {return btn1; }}

        public UserControl1()
        {
            InitializeComponent();
        }
        
        ...
Then we go to the test project and reach the control button with the property we defined and subscribe to click event as follows:
        ...
        test = new UserControl1();
        elementHost.Child = test;
        
        this.Controls.Add(elementHost);

        this.test.Button1.Click += (o, e) => 
        {
            this.test.Button1.Background = System.Windows.Media.Brushes.Aqua;
        };

    }
    ...
If we run the project again and click the button, the color of the button should change as we want:
WPF User Control in Winforms


No comments:

Post a Comment