Windows Forms interop

A couple months have passed since Deepak Kapoor and I wrote an article about Avalon-Windows Forms interop. (https://msdn.microsoft.com/library/en-us/dnlong/html/avalonwinformsinterop.asp)  I still point people to that article; even though it was written two CTP’s ago it’s still pretty accurate and is one of the best introductions on the subject.  But I do have a couple addendums.

WindowsFormsHost – You can use WindowsFormHost in xaml, and you can express Windows Forms controls in xaml, such as putting a Windows Forms button inside a WindowsFormHost:

      <wfh:WindowsFormsHost ID="windowsFormsHost">
        <wfh:WindowsFormsHost.Controls>
          <WinForms:Button Click=”whatever” Text=”I’m a button”/>
        </wfh:WindowsFormsHost.Controls>
      </wfh:WindowsFormsHost>

But that’s not something I recommend – what I suggest is defining a UserControl and putting that inside the WindowsFormsHost.  By creating a UserControl, you get the added bonus of being able to use Visual Studio to graphically design the Windows Forms portion of your application.  (Define a new user control using Visual Studio's Add new User Control -- right click on your project, click add\new item, select User Control.)  Your markup would look like:

      <wfh:WindowsFormsHost ID="windowsFormsHost">
          <mynamespace:UserControl1 x:Name=”whatever” />
      </wfh:WindowsFormsHost>

There’s a number of reasons I suggest this:

  • WindowsFormsHost was really designed to work with a single child, various things start to break if you put multiple Windows Forms controls directly inside the WindowsFormsHost.
  • Not all Windows Forms controls can be expressed in xaml.  Some can, some can’t.  Take for instance SplitContainer – in code, you write mySplitContainer.SplitterPanel1.BackColor = red, but xaml has no way to express “sub-properties” like SplitterPanel1.BackColor.
  • Did I mention the nice WYSIWYG designer with UserControl?

ElementHost – we didn’t show it, but when you put Avalon inside Windows Forms, you can use xaml for your Avalon.  Write a xaml file that’s all Avalon, just the way you would write a normal Avalon Page, then inside your Windows Forms initialization, include that page:

  elementHost.AddChild(new MyPage());

The hardest part of all this is convincing Visual Studio to understand xaml inside a Windows Forms project.  I haven’t figured out a good way to do this yet, so what I do it is create a new Avalon Control Library project, change the project settings to turn that into an executable instead of a DLL, and then copy in my Windows Forms code (including the Main method).  So a little ugly to set up, but once you get that done it really works quite nicely.

Finding WindowsFormsIntegration.dll -- In the May CTP, WindowsFormsIntegration.dll now ships as part of the SDK rather than in the main Avalon.msi.  You'll need to add a reference to it.  On my machine, the path is C:\Program Files\Reference Assemblies\Microsoft\Avalon\v2.0.50215\WindowsFormsIntegration.dll, although I can't swear I'm running exactly the same build as the May CTP so your path may vary slightly. If you haven't used that part of Visual Studio before, it's pretty easy -- go into the Solution Explorer, right click on "references", choose "Add References", go to the "Browse" tab, and pick that file.