将类似构建的WinForms.Form实例序列化为VB或C#源代码,就像IDE一样

Fas*_*tAl 3 c# vb.net codedom design-surface

我有大约500个由旧应用程序从XML文件动态生成的WinForms.我想自动将这些转换为我可以在设计器中编辑的VB或C#代码.

我可以手工完成,这需要永远......

或编写装入每个XML,调用旧的应用程序的XML到WinForm的建设者将其转换为一个完整的WinForm的应用程序,并检查每个控件的属性和使用StringBuilder来生成代码,设计师会吞噬.充其量只会是艰巨的.

但是:我想使用设计师使用的相同代码.我认为这将节省我的时间与角落案件.

我想要做的是,采取已建成的WinForm对象,以控制阵列全子控件(由旧的应用程序创建的XML到WinForm的代码),在IDE使用序列化设计的形式相同的代码把它到CodeDom,并获取我可以用真实语言保存的CodeDom语句列表.一旦我拿到CodeDOM,我会很高兴!

编辑

这个Codeproject文章体现了我想要做的事情的"概念":从一个完整的表单开始,将其转换('序列化')作为代码.然而,它有两个缺少:(1)它产生使用模板/ StringBuilder的.aspx页,而且那里的属性是(对于web表单细,但WinForms的串行化性质成实际.Designer.vb文件); (2)它是从头开始做到这一切的.我想重新使用visual studio的例程.他们允许您使用许多内容执行此操作,例如,属性网格.我只是想找到一篇文章的链接(也许我的google-fu太弱了),或者是某个人已经做过的短代码示例.

Pet*_*ter 5

所以这可能适合您的需求,也可能不适合您.我有一个解决方案,但它需要你调整你的XML - > WinForms渲染.

这很大程度上依赖于这个项目的使用:http://ivanz.com/files/docs/designerhosting/create-and-host-custom-designers-dot-net.html

下载EXE(它只是带有EULA的源代码的压缩版本)并构建解决方案,我在构建之前遇到了一些问题,直到我删除了对图形库的引用(以及从主机库中对它的相关调用).为什么主机库需要绘制图形我不太确定...

然后我构建了一个新的WinForms项目(不能是控制台,因为DesignSurface无法挂钩拖放事件).在新的winforms项目中引用上述项目中的Host和Loader项目.

在这里,您无疑需要调整现有流程.合并您现有的流程,使其适合我的标签下面显示的这种类型的表单构建:

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

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

        hc.DesignerHost.Container.Add(l);

        richTextBox1.Text = ((CodeDomHostLoader)hc.HostSurface.Loader).GetCode("C#");
Run Code Online (Sandbox Code Playgroud)

这将生成form.cs文件内容(请参阅下面生成的代码).这是一个多合一文件,您不需要创建单独的form.cs.designer文件来获得设计器支持.我复制了上面生成的代码,将其保存到.cs文件中,Visual Studio认为它是一个winform并给了我设计支持.

您的副本可能包含一个副主要.我进入了Loader - > CodeGen.cs文件并注释掉了与Main相关的部分,我建议你也这样做.

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.5448
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     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()
        {
            this.InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // 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";
            this.ResumeLayout(false);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

由FastAl编辑

彼得,你摇滚!这是非常正是我想要的.好吧,我不能完全抛弃它的对象; 只使用上面的方法,没有填充任何.Controls属性,所以我得到一个空白表单.此外,似乎必须由GetNewHost创建表单.幸运的是,我的XMl到屏幕例程实际上并没有创建容器,它只返回一个我必须正确重新显示的控件的平面列表(SetChildren sub).请注意我必须将它们添加到主机容器的注释,以便了解它们.它现在完美运作!

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)
        ControlFactoryLocator.AddService(_
            New PanelObjectFactoryWinFormAppSpecificCtls)
        ControlFactoryLocator.AddService(_
            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.
            Parent.Controls.Add(child)
            SetChildren(child, PO.Name, dsg, ctr)
        Next
    End Sub
End Module
Run Code Online (Sandbox Code Playgroud)