Introduction
This article discusses how to integrate a WPF XPS Document Viewer into a Windows Forms Application.
"WPF Rocks and offers a great future, we all should start to use it and change all our products over to it."
A great idea but for many of us, it's impossible. Our main product for example has thousands and thousands of lines of code and hundreds of forms. It would be economic suicide to put all that in the bin and start again. What would be nice though would be to develop new areas using WPF and integrate these with our Windows Forms solutions.
Background
A short while ago, I started to look at how we were going to deliver electronic documents. PDF has been the traditional approach but Microsoft's XPS offered so much more and so I decided to follow that path. From a programming point of view, it presented a number of challenges, creating, displaying, delivery, etc, my solutions to which I will share with you over the coming months but for now I am going to discuss the task of displaying an XPS document using the Document Viewer that comes with Visual Studio 2008 and embedding that into a Windows Forms solution. In doing so, hopefully I will demonstrate just how easy it is to integrate WPF with Windows Forms.
Using the Code
As an exercise, I have created a solution in VS2008 that consists of a WPF library class project and a Windows Forms Application project. The WPF project contains a Windows Forms user control that itself contains a WPF Document Viewer control. The Windows Forms project just contains a form used to demonstrate the use of the user control.
When you add a WPF library class, Visual Studio adds the basic references for you but since we will be adding a Windows Forms user control, we need to add a few extra references.
The following references are added by default:
PresentationCore
PresentationFramework
System
System.Core
System.Data
System.Data.DataSetExtensions
System.XML
System.Xml.Linq
WindowsBase
You will need to add a reference to:
ReachFramework
System.Drawing
System.Printing
System.Windows.Forms
UIAutomationProvider
WindowsFormsIntegration
Make sure your references are as above.
Add a WPF Usercontrol to the project and to this, add whatever WPF functionality you require. In my case, I have simply added a Windows Document Viewer.
We now need to add the Windows Forms User Control that we will expose to our Windows Forms Applications. In the code, add the following import statement.
Imports System.Windows.Forms.Integration
In the Forms Usercontrol, declare an instance of the WPF Usercontrol and in the load event, create the instance and do the plumbing. We do this by creating an instance of an ElementHost
. This is basically a container that is compatible with both Windows Forms and WPF. We create an instance of our WPF control and set it to be the child of the ElementHost
and then add the ElemenHost
to the control collection.
Private WithEvents wpfExtension As ParitorWPF.XPSDocumentViewer
Private Sub ParitorDocumentViewer_Load_
(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim host As New ElementHost
wpfExtension = New ParitorWPF.XPSDocumentViewer
host.Child = wpfExtension
host.Dock = Forms.DockStyle.Fill
Me.Controls.Add(host)
End Sub
We may also add pass-through methods to the user control to call into the WPF control or catch its events.
We can now add a form to the Windows Forms application and place our Windows Forms User Control on it. When we run the form, it displays the WPF application, in my case the Document Viewer.
It's as simple as that - so maybe we can't just replace our existing Windows Forms solutions but hopefully I've shown you just how easy it is to gradually add WPF functions to them.
History