Click here to Skip to main content
Click here to Skip to main content

Embedding a .NET WinForms Application in an Internet Browser Using WPF

By , 2 Dec 2008
 

Introduction

This article will describe how to embed a .NET Windows Forms application in a web browser using a WPF browser application. Basically, this article will show you how to web enable any Windows Forms .NET application with very few modifications to your project and no code modifications to your WinForms app.

Now, I realize that this is cheating, this article does not actually show you how to convert a .NET Windows Forms application to WPF. If you want to take advantage of all the features that come with WPF, eventually, you will need to re-write your GUI into WPF. However, if in the short term it is not feasible to convert all of your GUI code into WPF, then this solution is a primitive workaround that enables you to host your applications online.

Creating a sample Windows Forms application

The first step in this article will be to create a simple Windows Forms C# application. This can be any WinForms application, but for the purpose of this article, I will create a small application that calculates a Fibonacci number and displays it on the user interface. This WinForms application can be in either .NET 2.0 or 3.5.

1_VisualStudioCreateWinFormProject.jpg

My application will have a form called MainForm, a button called btnCalculate, and a text box called txtResult.

2_Fibonacci_WindowsForm.jpg

Here is the code for the button click event and the Fibonacci calculation:

static int Fibonacci(int x)
{
    if (x <= 1)
    {
        return 1;
    }
    return Fibonacci(x - 1) + Fibonacci(x - 2);
}

private void btnCalculate_Click(object sender, EventArgs e)
{
    txtResult.Text = Fibonacci(10).ToString();
}

Now that we have our sample application, the next step is to convert it to a Class Library. Right click on your project and choose Properties. Under the Application tab in the Output type combo box, choose Class Library, save, and rebuild.

3_ChangeProjectTypeToClassLibrary.jpg

Note, in order to have your application be referenced in WPF, this is the only change you will have to make to your Windows Forms project.

Creating a WPF browser host application

The next step will be to create a WPF browser application. You can do this within the same solution as your Windows Forms application, or in a new solution. In this sample, I am simply going to add the WPF browser application project to the same solution. I have called this new project WPFHost.

4_CreateWPFBrowserApplicationProject.jpg

The first thing we are going to do is add a reference from our WPFHost project to our WinForms Fibonacci application.

5_AddReference.jpg

Since the WinForms project is in the same solution, we will add the reference to the Fibonacci project. If the WinForms application was in a different solution, we would browse to the created DLL and add a reference to it.

6_AddReference.jpg

We will also need to add a reference to the Windows Forms Integration and System Windows Forms Component in the .NET tab.

7_AddReferenceWindowsFormsIntegration.jpg

8_AddReferenceSystemWindowsForms.jpg

The next step will be to add a StackPanel to our Page1 XAML window.

The full XAML for Page1.xaml is:

<Page x:Class="WPFHost.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1">
    <Grid>
        <StackPanel Margin="0,0,0,0" Name="stackPanel" 
           HorizontalAlignment="Left" VerticalAlignment="Top" />
    </Grid>
</Page>

OK, we are almost there. The next step will be to add some code to Page1.xaml.cs in our project. The magic will happen in the Page1 constructor. Our code will create a WindowsFormHost object and assign the previously created MainForm object from our Fibonacci assembly as the child. The WindowsFormHost will then be added as a child to our WPF StackPanel. The only other obscure line of code sets the TopLevel property of the MainForm object to false. I am not sure why this is required, but you will get a compile error if you do not add this step.

The code looks as follows:

using System.Windows.Controls;
using System.Windows.Forms.Integration;
using Fibonacci;

namespace WPFHost
{
    /// <summary>
    /// Interaction logic for Page1.xaml
    /// </summary>
    public partial class Page1 : Page
    {
        private readonly MainForm mainForm = new MainForm();

        public Page1()
        {
            InitializeComponent();

            //Create a Windows Forms Host to host a form
            WindowsFormsHost windowsFormsHost = new WindowsFormsHost();
            
            stackPanel.Width = mainForm.Width;
            stackPanel.Height = mainForm.Height;
            windowsFormsHost.Width = mainForm.Width;
            windowsFormsHost.Height = mainForm.Height;
          
            mainForm.TopLevel = false;

            windowsFormsHost.Child = mainForm;

            stackPanel.Children.Add(windowsFormsHost);
        }
    }
}

Don’t forget to Save.

OK, this is the last step, I promise. It is also the most obscure one that took me some time to figure out. When I first created the WPF project, I could get this code to work in a regular WPF application, but I always received a weird error when I tried it in a WPF browser application. I almost gave up, thinking that maybe it is not possible to host a Windows Forms application in a web browser. At the end, I found a post on Google groups that gave me the solution. The last step is to right click on the WPFHost project, choose Properties, and navigate to the Security tab. In the tab, change the radio button from “This is a partial trust application” to “This is a full trust application”.

10_FullTrustApplication.jpg

OK, I lied, there is one more step. Right click on your WPFHost project and choose “Set as Startup Project”.

Save, Compile, and Run. You should see your default web browser open with the following page:

11_FinalOutput.jpg

Conclusion

That’s it. If you wish to embed the created .xbap in an HTML web page, you can use the <iframe> tag as follows:

<iframe src="WPFHost.xbap" width="329" height="443" />

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Adam Berent
Canada Canada
Member

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionFix Form Move?memberNguyenTrungHieu19 Oct '09 - 6:34 
Hi,
That's an Exellent tutorial.
But I got a problem. When I use in iframe tag in html, the form can be moved around by mouse. Does anyone have any idea to fix this problem?
Thanks.
GeneralThank you so mcuh. I have a question regarding the 2 "disabled" navigation buttons above "MainForm"memberkwandalara12 Feb '09 - 19:16 
Hello Adam,
 
First I'd like to thank you for this great tutorial.
 
As I follow up and with all tips from all replies, I have successfully reached the last step you demonstrated. Very cool indeed. However, I googled the internet and no luck to figure out as how to get rid of the 2 "disabled navigation like buttons" right above "MainForm".... I don't really know why they are there and simply because they seemed useless that I'd like to know how to have them not shown on the page.
 
Thanks ahead for any tips.
GeneralFull-Screen hosted WinFormsmemberRonchen7773 Feb '09 - 22:23 
Great article!Thumbs Up | :thumbsup: For all those who search how to display the hosted WinForms in full screen mode, you can consider to adapt the following changes to the article's sample:
 
In the Page1.xaml remove the <b>StackPanel</b> and the <b>Grid</b>, and insert an <b>WindowsFormsHost</b> control with the following properties:
<pre>
&lt;WindowsFormsHost HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="windowsFormsHost1"/&gt;
</pre>
 
Then, in the Page1.xaml.cs use this constructor:
<pre>
<code>
public Page1()
{
InitializeComponent();
mainForm.WindowState = FormWindowState.Maximized;
mainForm.TopLevel = false;
windowsFormsHost1.Child = mainForm;
}
</code>
</pre>
and that's it!
Thanks again for the inspiration!
Ron<b></b>
GeneralThanksmembersilver_surfer14 Dec '08 - 16:41 
Thanks for your excelent article. I hadn't work before with WPF, But this gave me a good exposure and an enthusiasm to work with WPF
 
~$!|v3r $urf3r~
http:\\risingofsilversurfer.blogspot.com

GeneralThanksmemberronzulu13 Dec '08 - 14:00 
Thanks for this... I didn't even know this was possible!
 
Cheers
Ronny
GeneralCannot create instance of 'Page1' defined in assembly 'WPFHostmemberAndrusM9 Dec '08 - 8:49 
I tried this with my application but got error
 
System.Windows.Markup.XamlParseException was unhandled
Message: Cannot create instance of 'Page1' defined in assembly 'WPFHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Exception has been thrown by the target of an invocation. Error in markup file 'Page1.xaml' Line 1 Position 7.

 
page1.xaml contains:
 
<Page x:Class="WPFHost.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1">
    <Grid>
        <StackPanel Margin="0,0,0,0" Name="stackPanel" 
           HorizontalAlignment="Left" VerticalAlignment="Top" />
    </Grid>
</Page>
 
How to fix?
 
Andrus

GeneralRe: Cannot create instance of 'Page1' defined in assembly 'WPFHostmemberAdam Berent12 Dec '08 - 3:29 
Did you do the last step of setting the application to full trust?
 

GeneralRe: Cannot create instance of 'Page1' defined in assembly 'WPFHostmemberje_gonzalez25 Dec '08 - 8:17 
Did you get any further with your error? I get the same...
GeneralRe: Cannot create instance of 'Page1' defined in assembly 'WPFHostmemberAdam Berent2 Jan '09 - 3:27 
Ok but no one answered if they completed the the last step of setting the application to full trust? If you do not set the application to full trust you will get this error.
 

GeneralRe: Cannot create instance of 'Page1' defined in assembly 'WPFHostmemberahaid@hotmail.com27 Feb '09 - 8:42 
I'm getting the same error even though I made sure the "full trust" setting was on.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 2 Dec 2008
Article Copyright 2008 by Adam Berent
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid