Ok, so before you ask why on earth would you bother let me explain :)

As part of my work over at ClarionAddins I am always looking for way to improve the user experience as well as stretching my knowledge of .Net programming. I thought it might be nice to use WPF but since the Clarion IDE is targeting v2.0 of the .Net framework this is not so easy. Hence this example!

Of course there are many resources out there related to this topic, see below, but nothing I could discover specific to v2.0 so for me it took a little work to get there. I learnt a lot about reflection along the way!

This code assumes that the v3.5 Framework is installed on the target machine. For production it would of course be necessary to test for this and react accordingly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
 
namespace ClarionAddins.WpfTest
{
    public partial class WpfTestForm : Form
    {
        public WpfTestForm ()
        {
            InitializeComponent();
            AddWpfControl();
        }
 
        private void AddWpfControl()
        {
            // You need a full AssemblyQualifiedName for the elementHost class
            string elementHostQualifiedName = "System.Windows.Forms.Integration.ElementHost, WindowsFormsIntegration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            // Using this it is possible to load the ElementHost class at runtime and create an instance we can use
            Type elemHostType = Type.GetType(elementHostQualifiedName, true);
            object ctrlHost = Activator.CreateInstance(elemHostType);
            // Dock this ElementHost into our WinForms control container
            MethodInfo info = elemHostType.GetMethod("Dock");
            elemHostType.GetProperty("Dock").SetValue(ctrlHost, DockStyle.Fill, null);
            // Finally, add the ElementHost to the WinForms list of controls
            this.Controls.Add((Control)ctrlHost);
 
            // Now, load the WPF UserControl to be displayed
            string currentPath = Path.GetDirectoryName((new System.Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath);
            string userControlPath = Path.Combine(currentPath, "WpfControlLibrary.dll");
            Assembly assembly = Assembly.LoadFrom(userControlPath);
            Type userControlType = assembly.GetType("WpfControlLibrary.MyUserControl", true);
            // Create an instance of the UserControl and call the InitializeComponent method
            object userControl = Activator.CreateInstance(userControlType);
            info = userControlType.GetMethod("InitializeComponent");
            info.Invoke(userControl, null);
 
            // Last of all, attach the UserControl to the ElementHost !
            elemHostType.GetProperty("Child").SetValue(ctrlHost, userControl, null);
        }
    }
}

Here is a screenshot of this technique being used in an addin I am working on:

WPF UserControl in an Addin Pad!

-brahn