I have a strange fascination with hybrids. Combining old and new technologies in bizarre and interesting ways. Why must developers make “the choice” between a web or native technology? It would be great to build applications that would increase or decrease in features depending on the platform they were run on.
Do you have a Winforms application that you’d like to host in a web browser? There’s an interesting technique you can use to do this enabled by .net Framework 3.5.
The .net framework provides the ability to create WPF web applications (commonly called XBAP). WPF has the ability, in turn, to host Winforms.
Security
It appears that in order to do this effectively, it’s necessary to deploy your XBAP application as a “Full Trust” application.
The code
To use this, create an XBAP project, then a page a “WinformHost” control on it. The XAML could look like this:
<Page x:Class="Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
<DockPanel LastChildFill="True">
<Button Name="Button1" DockPanel.Dock="Bottom" >This is a WPF Button</Button>
<WindowsFormsHost Name="WinformHost" />
</DockPanel>
</Page>
Then, create some code to instantiate your winform and show it on the Winform host:
Class Page1
Private Sub Page1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Dim loForm As New HelloWorldWinform
WinformHost.Child = WinformToUserControl.GetWrapper(loForm)
loForm.Show()
End Sub
End Class
Here’s the subroutine:
Public NotInheritable Class WinformToUserControl
Public Shared Function GetWrapper(ByVal form As System.Windows.Forms.Form) As System.Windows.Forms.Control
Dim loPanel As New System.Windows.Forms.Panel
loPanel.Dock = Forms.DockStyle.Fill
ShowFormInControl(loPanel, form)
Return loPanel
End Function
Private Shared Sub ShowFormInControl(ByVal ctl As System.Windows.Forms.Control, ByVal frm As System.Windows.Forms.Form)
frm.TopLevel = False
frm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
frm.AutoScaleMode = Forms.AutoScaleMode.Dpi
ctl.Controls.Add(frm)
frm.Dock = Forms.DockStyle.Fill
End Sub
End Class
Interesting bits and pieces
We found that in order for the items inside the control to scale properly, the AutoScaleMode property on the Winform must be set to Dpi instead of the default, which is Font. I have a feeling this is because Dpi is the mode preferred for WPF, but I am uncertain.
In the sample WinformToUserControl class I found it better to contain the Winform inside a panel rather than exposing the Winform directly. It seemed to make it more stable. Feel free to experiment with taking it off.
Gotchas
As of time of writing, Firefox on my Windows 7 64 bit machine steadfastly refuses to run xbap. It appears the “Windows Presentation Foundation” addin has not been automatically installed. I have no idea how to install it. There’ appears to be no information about how to do so. So if you have it, good for you. If you don’t….try re-installing the .net framework 3.51 (which didn’t work for me…)
I do know there was some controversy about this addin being temporarily blacklisted by Mozilla due to security concerns last month, but that’s all over now isn’t it?
Download
You can download a sample project here.
Links
- I didn’t use anything from this project, but you might find it interesting MdiWindowManager
- StackOverflow post on Embedding winforms in usercontrols