表单设计器的简单思路

简介:

  在之前的一篇文章中提到了,在MVC中我需要动态生成表单,而这个表单是根据自定义的表单设计器设计出来的。详见:ASP.NET MVC 2生成动态表单的一种最简单的思路。这篇文章,我将演示一下我开发的一个简易的WPF表单设计器,以及这样设计的思路。

    这样设计的思路很简单:由WPF设计器产生一个XML文件,然后将这个XML文件保存起来,然后在Asp.net MVC项目根据条件查找出XML表单,随后将它解析成HTML。

    这种方式的优点是:由于有一个WPF的客户端设计器,用户在制作表单的时候就会比较方便。不会存在浏览器上设计表单的诸多问题。

    这种方式的缺点是:设计出来的表单是XML的,还需要转换成HTML,转换和定位都非常麻烦。

    看下那篇文章的XML结构:

<?xml version="1.0" encoding="utf-8" ?>
<form name="form1">
    <field type="text" name ="firstname" class ="textbox" left="300"  top="200"></field>
    <field type="text" name ="lastname" class ="textbox" left="700"  top="200">祁林</field>
    <field type="text" name ="sex" class ="textbox" left="300"  top="240"></field>
    <field type="text" name ="age" class ="textbox" left="700"  top="240">24</field>
</form>

    这个文件中的div使用了绝对布局,这样的方式固然问题多多,但是在我还没想到更好的办法之前,我还是使用这种方式去生产表单,以便能继续下去。其实使用table就可以用不着div的绝对布局了,只是我还没有找到在WPF设计器上画Table的方法。

   下面看下这种思路的一个简单的Demo:在WPF设计器中设计一个登陆界面表单,然后在MVC中解析这个表单。

    我实现的这个WPF表单设计器的界面如下图,有点类似VS。上边是菜单,左边是工具栏,中间是设计区,右边是属性框。

ppp

通过拖拽设计一个登陆界面:

ppp2

使用下面代码,将界面上的元素转化成XML。

public XElement SerializeDesignerItems(IEnumerable<DesignerItem> designerItems)
{
    string contentXaml;
    XElement serializedItem = null;
    XElement serializedItems = new XElement("Form");
    foreach (DesignerItem item in designerItems)
    {
        
        contentXaml = XamlWriter.Save(((DesignerItem)item).Content);
        XElement XElementName = null;
        XElement XElementType = null;
        XElement XElementValue = null;
        object obj = ((DesignerItem)item).Content;
        switch (obj.GetType().Name)
        {
            case "Button":
                XElementName = new XElement("Name",(obj as Button).Name);
                XElementType = new XElement("Type", "button");
                XElementValue = new XElement("Value", (obj as Button).Content);
                break;
            case "ComboBox": 
                XElementName = new XElement("Name",(obj as ComboBox).Name);
                XElementType = new XElement("Type", "select");
                string value = "";
                foreach (ComboBoxItem cb in (obj as ComboBox).Items)
                {
                    value = value+":"+cb.Content;
                }
                value = value.Substring(1, value.Length - 1);
                XElementValue = new XElement("Value", value);
                break;
            case "Label":
                XElementName = new XElement("Name",(obj as Label).Name);
                XElementType = new XElement("Type", "label");
                XElementValue = new XElement("Value", (obj as Label).Content);
                break;
            case "TextBox": 
                XElementName = new XElement("Name",(obj as TextBox).Name);
                XElementType = new XElement("Type", "text");
                XElementValue = new XElement("Value", (obj as TextBox).Text);
                break;
            case "RadioButton":
                XElementName =new XElement("Name",(obj as RadioButton).Name);
                XElementType = new XElement("Type", "radio");
                XElementValue = new XElement("Value", (obj as RadioButton).Content);
                break;
            case "CheckBox": 
                XElementName =new XElement("Name",(obj as CheckBox).Name);
                XElementType = new XElement("Type", "checkbox");
                XElementValue = new XElement("Value", (obj as CheckBox).Content);
                break;
 

        }
        XElement XElementLeft = new XElement("Left", Canvas.GetLeft(item)+100);
        XElement XElementTop = new XElement("Top", Canvas.GetTop(item)+100);
        XElement XElementWidth = new XElement("Width", item.Width);
        XElement XElementHeight = new XElement("Height", item.Height);
        XElement XElementContent = new XElement("Content", contentXaml);
        serializedItem = new XElement("field", XElementName,XElementType,XElementValue, XElementLeft, XElementTop, XElementWidth, XElementHeight, XElementContent);
        serializedItems.Add(serializedItem);
    }

    return serializedItems;
}

在Asp.net MVC项目中使用下面代码将XML转换成HTML:

<% XElement xml = (XElement)ViewData["xml"]; %> 
 <%Html.BeginForm(); %>  
             <%
                 StringBuilder sb = new StringBuilder();
string label = " <div  style=\"left: {0}px; position: absolute; top: {1}px\">{2}</div>";
                 string input = "<input name=\"{0}\" type=\"{1}\"    style=\"left: {2}px; position: absolute; top: {3}px;width:{4}px; height:{5}px\"  value=\"{6}\"></input>";
                 string checkbox = "<input name=\"{0}\" type=\"{1}\"    style=\"left: {2}px; position: absolute; top: {3}px;width:{4}px; height:{5}px\"  ><div style=\"left: {7}px; position: absolute; top: {8}px;\">{6}</div></input>";
                 sb.Append("<div style=\"height:200px\"> ");
                 foreach(XElement f in xml.Elements()) 
                 {
                     if (f.Element("Type").Value == "label")
                     {
                         sb.Append(string.Format(label, Double.Parse(f.Element("Left").Value) - 60, f.Element("Top").Value, f.Element("Value").Value));
                     }
                     else if (f.Element("Type").Value == "checkbox")
                     {
                         sb.Append(string.Format(checkbox, f.Element("Name").Value, f.Element("Type").Value, f.Element("Left").Value, f.Element("Top").Value, f.Element("Width").Value, f.Element("Height").Value, f.Element("Value").Value, Double.Parse(f.Element("Left").Value) + 50, Double.Parse(f.Element("Top").Value) +8));   
                     }
                     else
                     {
                         sb.Append(string.Format(input, f.Element("Name").Value, f.Element("Type").Value, f.Element("Left").Value, f.Element("Top").Value, f.Element("Width").Value, f.Element("Height").Value, f.Element("Value").Value));
                     }
                 }
                 sb.Append("</div > ");
                 Response.Write(sb.ToString());
                 %> 
      
 <%Html.EndForm(); %> 
在Asp.net MVC中显示的登陆界面:
ppp4 

 

总结:本文主要是讲述了实现一个表单设计器的简单思路。如果有什么疑问,或者更好的办法(最好能有Demo),欢迎能一起讨论。





本文转自麒麟博客园博客,原文链接:http://www.cnblogs.com/zhuqil/archive/2010/08/20/wpf-form-designer.html,如需转载请自行联系原作者

相关文章
|
6月前
|
数据可视化 数据挖掘 API
5 款热门的表单设计器推荐
5 款热门的表单设计器推荐
|
移动开发 前端开发 JavaScript
利用前端技术写爱心页面的一些思路
作为前端开发者,我们常常不仅需要构建漂亮的、高效的网站,还需要为用户提供更多的情感体验。其中一种情感表达方式就是利用前端技术实现爱心特效。下面我将分享几种实现方式。
285 0
|
前端开发
前端学习案例19-加入元素的测试
前端学习案例19-加入元素的测试
71 0
前端学习案例19-加入元素的测试
|
存储 JavaScript API
移动端单模块功能实现思路及重要方法总结
移动端单模块功能实现思路及重要方法总结
移动端单模块功能实现思路及重要方法总结
|
安全 数据安全/隐私保护 对象存储
表单的 9 种设计技巧【上】
表单是信息添加、录入的通用形式,合理的表单设计能减轻用户负担。这里码匠提供了一些表单设计的简单技巧。
737 0
表单的 9 种设计技巧【上】
|
存储 前端开发 数据可视化
实现一个表单设计器我们需要知道的
表单功能一直是前端项目中比不可少的一块功能,如果有个项目需要在两个月内开发200个左右表单,那我们应该怎么办?加班加点也是能搞出来的,那质量有保证么,这是我们就需要开发一个可以通过可视化交互设计表单的功能。下面和大家分享下我在开发这款表单设计器时使用的技术能力以及整个的设计思路。
|
JSON 前端开发 测试技术
【测试开发】十三、接口测试-接口定义功能-前端-实现动态增删表单
【测试开发】十三、接口测试-接口定义功能-前端-实现动态增删表单
【测试开发】十三、接口测试-接口定义功能-前端-实现动态增删表单
|
安全 数据库 数据安全/隐私保护
表单的 9 种设计技巧【下】
表单是信息添加、录入的通用形式,合理的表单设计能减轻用户负担。这里码匠提供的一些表单设计的简单技巧的下篇。
212 0
表单的 9 种设计技巧【下】
|
测试技术 Python
接口测试平台代码实现4:第一个页面
好了,咱书接上回,我们目前已经项目和app都创建好了。 现在我们用pycharm来打开这个项目,记住要选择到项目上(也就是ApiTest),层级别选错了,选对的话,pycharm是可以自动识别出来这是个django项目,给你安排好启动服务功能的哦~
接口测试平台代码实现4:第一个页面
|
JSON 监控 前端开发
接口测试平台代码实现5:亲手创造第一个首页
接口测试平台代码实现5:亲手创造第一个首页
接口测试平台代码实现5:亲手创造第一个首页