Take the 2-minute tour ×

I have about 500 WinForms that are generated dynamically from XML files by an old app. I would like to automatically convert these to VB or C# code I can edit in the designer.

I can do it by hand, which would take forever...

Or write an app that loads each XML, calls the old app's xml-to-winform-builder to convert it to a completed WinForm, and examine every control's property and use StringBuilder to generate code that the designer will swallow. Which would be arduous at best.

BUT: I would like to use the same code that the designer uses. This I think will save me time with corner cases.

What I would like to do is, take an already built WinForm object, with control arrays full of child controls (created by the old apps xml-to-winform code), throw it at the same code the IDE uses to serialize the designed form to CodeDom, and get back a CodeDom list of statements I can save in a real language. Once I get the CodeDOM I'll be happy!


This Codeproject article embodies the 'concept' of what I want to do: Start with a completed form, convert it ('serialize it') as code. However, it has two lacks: (1) it generates the .aspx page using templates/stringbuilder, and that is where the properties are (fine for webforms, but winforms serializes the properties into the actual .Designer.vb file); (2) it does this all from the ground up. I want to re-use visual studio's routines. They let you do this with many things, for example, the property grid. I'm just seeking a link to an article (maybe my google-fu was too weak), or, a short code sample from something somebody has already done.

share|improve this question
Why the extra step ? Why not go xml to c#/vb directly ? –  Tommy Grovnes Jul 14 '12 at 9:26
The IDE in question is Visual Studio and most of the code that implements the designers is either native (not reusable at all), or .NET but implemented in private assemblies or private/internal classes. –  Simon Mourier Jul 15 '12 at 14:51
Just to make sure I've got this right: You have a ton of Forms defined using XML, you have code that will convert this XML into a WinForms object. Now you want to take this process which can automatically generate WinForms using XML templates and make it all hard coded, but with Designer support? What are you hoping to gain by having designer support? Are you planning on dropping the xml templating solution? –  Peter Jul 16 '12 at 14:51
@Tommy - Current system can process the XML files, however editing is a pain. Have to do it by hand. Like making an HTML form in notepad. Want to convert to code so I can use the IDE's winforms editor and drag and drop (coming into the 90s here). –  FastAl Jul 16 '12 at 16:12
@Peter - 'What am I hoping to gain' - the ability to edit the form design with the IDE's WinForms designer. Right now it's like making HTML forms with notepad. This way, I don't have to write an editor for the properietary format. Converting to HTML and using an HTML editor would allow for changing the visuals but not databinding, etc. that is WinForms extra. I have a converter already to write new screens I'm designing out to XML. –  FastAl Jul 16 '12 at 16:18
show 3 more comments

1 Answer

up vote 5 down vote accepted

So this may or may not fit your needs. I have a solution but it will require that you tweak your XML -> WinForms rendering.

This relies heavily on the use of this project: http://ivanz.com/files/docs/designerhosting/create-and-host-custom-designers-dot-net.html

Download the EXE (which is just a compressed version of the source with a EULA) and build the solution, I had some issues with building until I removed references to the graphing library (and the associated calls to it from the Host library). Why the Host library needs to draw graphs I'm not really sure...

Then I built a new WinForms project (can't be console because the DesignSurface fails to hook into drag/drop event). Reference the Host and Loader projects from the above project in your new winforms project.

Here is where you will undoubtably need to tweak your existing process. Merge your existing process so that it fits into this type of form building shown for my label below:

        HostSurfaceManager hsm = new HostSurfaceManager();
        HostControl hc = hsm.GetNewHost(typeof(Form), LoaderType.CodeDomDesignerLoader);

        var l = new Label() { Text = "TEST!!!!" };


        richTextBox1.Text = ((CodeDomHostLoader)hc.HostSurface.Loader).GetCode("C#");

This generates your form.cs file content (see generated code below). This is an all in one file, you do not need to create a seperate form.cs.designer file to get designer support. I copied the code generated above, saved it to a .cs file, and visual studio recognized it as a winform and gave me design support.

Your copy will probably include a sub Main. I went into the Loader -> CodeGen.cs file and commented out the section related to Main, I would suggest you do the same.

// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.5448
//     the code is regenerated.
// </auto-generated>

namespace DesignerHostSample
    using System;
    using System.ComponentModel;
    using System.Windows.Forms;

    public class Form1 : System.Windows.Forms.Form

        private System.Windows.Forms.Label label1;

        public Form1()

        private void InitializeComponent()
            this.label1 = new System.Windows.Forms.Label();
            // label1
            this.label1.Location = new System.Drawing.Point(0, 0);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(100, 23);
            this.label1.TabIndex = 0;
            this.label1.Text = "TEST!!!!";
            // Form1
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Name = "Form1";

edit by FastAl

Peter, you rock!!! This is pretty much exactly what I wanted. Well, I can't exactly just throw the object at it yet; using just the above method, none of the .Controls properties were filled, so I got a blank form. Also it seems like the form has to be created by GetNewHost. Fortunately my XMl-to-screen routine doesn't actually create the container, it just returns a flat list of controls that I must properly reparent (SetChildren sub). Note the comment where I have to add them to the host container for it to know about them. NOW it works perfectly!

Public Module Main
    Public Sub Main()
        Dim FormSpecAsText As String = ...  read XML form def from file
        Dim Outfile As String = ... output file is in my project 

        ' Setup for Winforms platform
        Dim dsg As New DynamicScreenGenerator
        Dim ListOfControls As New PanelObjectList
        ControlFactoryLocator.AddService( _
            New PanelObjectFactoryWinFormBasicControls)
            New PanelObjectFactoryWinFormAppSpecificCtls)
            New PanelObjectFactoryWinFormFormEditorCtls)

        ' Deserialize FormSpecAsText into a flat list of Controls
        ListOfControls.AddRange( _
            dsg.BuildDSGLists(FormSpecAsText, ListOfControls).ToArray)

        ' setup for serialization to Code
        Dim hsm As New Host.HostSurfaceManager
        Dim hc As Host.HostControl = _
          hsm.GetNewHost(GetType(Form), Host.LoaderType.CodeDomDesignerLoader)

        ' Get main form that was created via GetNewHost, autosize it
        Dim HostUserControl = _
            CType(hc.DesignerHost.Container.Components(0), Form)

        ' Parent them properly, and add to host (top lvl ctls have parent="")
        SetChildren(HostUserControl, "", dsg, hc.DesignerHost.Container)
        HostUserControl.AutoSize = True

        ' write serialized version to a file in my project
        IO.File.WriteAllText(Outfile, _
          CType(hc.HostSurface.Loader, Loader.CodeDomHostLoader).GetCode("VB"))
    End Sub

    Sub SetChildren(ByVal Parent As Control, ByVal ParentName As String, _
           ByVal dsg As DynamicScreenGenerator, ByVal ctr As IContainer)
        For Each PO In (From p In dsg.POList Where p.Parent = ParentName)
            Dim child = CType(dsg.CTLList(PO), Control)
            ctr.Add(child, PO.Name) ' seem to have to add to container while 
             '  parenting them or .Controls isn't serialized and form is blank.
            SetChildren(child, PO.Name, dsg, ctr)
    End Sub
End Module
share|improve this answer
@FastAI - Glad I could help you get it going. I didn't have any way to really get the kinks worked out since I wrote this just for you, so thanks for posting your revision. –  Peter Jul 17 '12 at 19:38
add comment

Your Answer


