Many people asked me for a simple tutorial that explain how to create a template for converting a control in Windows Forms to XAML (WF2XAML for friends).
Well, it’s a pretty easy task. First, you must download the binaries of WF(2)XAML here. Then, after unpacking it, create a new C# (or VB.net) Library in Visual Studio. In this tutorial we will name it ACME.Templates, but feel free to name it as you wish.
We will create a new version of the button template, so WF(2)XAML will use this template when it will convert Windows Forms to WPF Windows (or Pages).
Add a reference to System.Windows.Forms.dll and to Ingenium.WF2XAML.dll in your project, so the BaseTemplate Class is visible in your project.
Create a Class, name it ACME.Templates.ButtonTemplate and make it inherit from Ingenium.WF2XAML.Templates.BaseTemplate.
1: namespace ACME.Templates
2: {
3: public class ButtonTemplate : Ingenium.WF2XAML.Templates.BaseTemplate
4: {
5: public override System.Xml.XmlElement RenderToWPF(System.Xml.XmlDocument document)
6: {
7: //Fill with custom conversion code...
8: }
9: }
10: }
Override the method RenderToWPF and you’re done!
Well, you may argue, what I must write inside that method? The method must return an XmlElement, so you are responsible to create it, fill it with properties and attributes and return to the engine (the last passage is pretty automatic; in fact you sould only add the statement return _element;)
The base class BaseTemplate has a property Control of type Control that the engine fills with the converting control. In our case, this.Control will contain the instance of Button control that we are going to convert. So, we can use every property of the control to make aour calculations and/or evaluations to emit WPF code. Let’s see a simple code snippet:
1: using System.Xml;
2: using Ingenium.WF2XAML.Templates;
3:
4: namespace ACME.Templates
5: {
6: public class ButtonTemplate : Ingenium.WF2XAML.Templates.BaseTemplate
7: {
8: public override System.Xml.XmlElement RenderToWPF(System.Xml.XmlDocument document)
9: {
10: //Create Element...
11: XmlElement _rootNode = document.CreateElement("Button");
12:
13: //Examine converting control properties and convert them in new properties
14: _rootNode.SetAttribute("Name", Globals.X_NAMESPACE, Control.Name);
15: _rootNode.SetAttribute("Width", Control.Width.ToString());
16: _rootNode.SetAttribute("Height", Control.Height.ToString());
17: _rootNode.SetAttribute("Canvas.Top", Control.Top.ToString());
18: _rootNode.SetAttribute("Canvas.Left", Control.Left.ToString());
19: _rootNode.SetAttribute("Content", Control.Text);
20:
21: //Add some hard coded properties
22: _rootNode.SetAttribute("FontFamily", "Verdana");
23: _rootNode.SetAttribute("Foreground", "#FFFFFFFF");
24:
25: //Add other transformations or add styles/triggers/animations...
26: return _rootNode;
27: }
28: }
29: }
Ok, now compile the class library and copy the dll ACME.Templates.dll in the same directory where resides files of WF2XAML unzipped early. The last step to use your newly created template is to “register” it in the conversion engine. This is made in the WF2XAML.exe.config file. In detail, we must change the row:
<Template ControlName="System.Windows.Forms.Button" ClassName="Ingenium.WF2XAML.Templates.ButtonTemplate, Ingenium.WF2XAML.Templates"/>
in
<Template ControlName="System.Windows.Forms.Button" ClassName="ACME.Templates.ButtonTemplate, ACME.Templates"/>
If you launch WF2XAML to convert a Windows Forms in WPF, every System.Windows.Forms.Button will be converted using your template. Obviously enough, the same explained technique could be applied to User Controls. Please feel free to contact me to report problems, wish lists, and things you may think useful to enhance the conversion process. Happy converting and templating!