表单设计器的简单思路

  1. 云栖社区>
  2. 博客>
  3. 正文

表单设计器的简单思路

技术mix呢 2018-01-03 13:10:00 浏览806
展开阅读全文

  在之前的一篇文章中提到了,在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中显示的登陆界面:
 

 

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





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

网友评论

登录后评论
0/500
评论
技术mix呢
+ 关注