.NET窗口定制的持久化――
《通过用 .NET 生成自定义窗体设计器来定制应用程序》的补充
http://www.iseast.com
如果是对.Net的IDE设计环境比较感兴趣的话,相信您已经读过《通过用 .NET 生成自定义窗体设计器来定制应用程序》了,作者用详细的讲解内容和简明的源码向我们展示了实现的过程和机制,是我们很好的学习实例:http://www.microsoft.com/china/MSDN/library/netFramework/netframework/CustomFormsDesigner.mspx,其核心关键一是取得控件的设计视图DesignView并添加到主窗口中,其次是实现IToolboxService接口并连接到程序中,从而实现了一个可拖放和编辑控件的可视化环境。
在下载作者提供的源码并运行之后,其表现的效果让我非常兴奋,实现一个自己的IDE环境如此方便,不得不佩服微软设计VS的时候对开放性的规划。同时其组件空间的寻找和类反射的运用也已经非常到位。不过在使用几次之后,我就发现有些遗憾,为什么每次设计的结果不能保存呢,下次还要重新来过。可能作者只是想重点说明ItoolboxService接口,所以才没有全部完成吧。下面就看看如何能新建,打开,保存自己设计的界面。
首先,我们看如何实现设计结果的保存。其基本思路是,使用结构化的XML文件,按照窗口上控件的叠方层次依次产生每个控件的XMl节点,并把该控件的属性值填入节点的对应字段。最后把整个XML文件保存下来就可以了。在这其中因为要从对象实体中读取属性名称和其数值,所以大量的用到类反射技术。如根据控件类名创建一个控件的XML节点的代码:
XmlElement el = doc.CreateElement(o.GetType().FullName);
读出其Name属性并加入节点的过程如下:
XmlElement childEl = doc.CreateElement("Name");
XmlAttribute valueAttribute = doc.CreateAttribute("value");
valueAttribute.InnerText = ctrl.Name;
childEl.Attributes.Append(valueAttribute);
el.AppendChild(childEl);
然后就是遍历访问其子控件并加入到自己的Controls节点中就可以了,其中类似的还涉及到对ILIST属性的保存。一个包含一个Label的窗口保存后文件内容如下:
<Components version="1.0">
<System.Windows.Forms.Form>
<Name value="Form1" />
<ClientSize value="{Width=424, Height=359}" />
<DockPadding value="" />
<Text value="New Form1" />
<Controls>
<System.Windows.Forms.Label>
<Name value="Label2" />
<Text value="subject" />
<TabIndex value="2" />
<Location value="{X=40,Y=160}" />
</System.Windows.Forms.Label>
</System.Windows.Forms.TextBox>
</Controls>
</System.Windows.Forms.Form>
</Components>
保存完之后,我们要做的就是读取文件并恢复设计的界面了。跟写入的过程刚好相反。先读入XML文件,然后根据每个节点的内容生成其所表达的控件实体,并对其属性逐个赋值,然后把控件添加到其父节点上。这其中比较麻烦的应该是读出控件的值并赋给对象实体了,不但要通过类反射从类名创建对象,还要取得属性名称并对控件数值,其中还要对不同类型的值如数字和字串进行正确的类型转换。所有这些工作,都是通过一个ItypeResolutionService的实现来完成的。例如public Type GetType(string name)就是通过类名称返回一个Type,然后host.CreateComponent(newObject.GetType(), componentName);就可以创建这个对象了。
完成了以上功能后,这个编辑器基本上实现了新建,修改,保存这样一个完整的周期。以这个程序为基础,可以实现用户的自定义界面和可视化程序的自动产生了。下载完整程序和源码请登陆网站http://www.iseast.com/DesktopDefault.aspx?tabindex=3&tabid=7