文/lijun4017 出处/博客园
其实这是我的一个两年前的项目中用到的东西,今天刚好翻以前的代码,看到,觉得也是自己想出来的东西,写写也无妨,哪怕是为了填充我空虚的blog。这个是一个智能客户端,但是里面涉及的表单非常之多,统计一下,有200个张。本来也不是问题,用FORM一个一个画也能够画出来,但是这样有几个缺点,一方面导致智能客户端的dll变的比较大,每次更新的时候,都要下载整个dll;一方面分工不好分,原来那个公司那时候只有我用过winform,老板就把这个任务分配给我了。但是我一个人,要做那么多的表单,而且在比较短的时间内,也不是说不可能,太累了。我想想看能不能有其他方法。
当时XFORM的概念相当热,我也看了一些资料,觉得还是不太成熟,没有敢用。
后来看了微软office2007中的infopath,感觉功能非常强,它可以实现用infopath设计表单,然后用表单控件把表单嵌入到winform中去,并且可以实现表单中的数据加载和保存功能。但是唯一的遗憾就是如果要使用它,就必须要客户机器上安装office2007,这样就不太现实了。
最后来想到的是用xml+xslt是动态生成静态页面,然后把静态页面嵌入在winform的浏览器控件里面,并且屏蔽一些浏览器控件的一些属性,看起来就和winform设计的表单差不多了。这样就方便多了,我可以叫美工帮我设计表单,叫其他的asp.net的程序员帮忙做XML和XSLT以及里面的javascript脚本。后来的项目进展说明了,这种方式真的大大的提高了工作效率,也让我轻松了不少,嘿嘿,又偷懒了。
下面我说说具体的过程吧。
1.首先我在设计表的时候,把整个表单的内容设计成XML类型的字段,当然,其他需要搜索的字段还是要单独建字段,并且保存xslt文件的版本号。
2.设计表单的XML结构,下面是示例。
- <?xml version="1.0" encoding="utf-8" ?>
- <!--现场会议记录-->
- <meetnote>
- <enterprise></enterprise>
- <!--会议名称-->
- <meets>
- <meet>
- <name>meet1</name>
- <checked>false</checked>
- </meet>
- <meet>
- <name>meet2</name>
- <checked>false</checked>
- </meet>
- <meet>
- <name>meet3</name>
- <checked>false</checked>
- </meet>
- </meets>
- <compere />
- <recorder />
- <address />
- <meetdate />
- <content />
- </meetnote>
复制代码3.设计表单的XSLT文件,下面是示例。
4.在XSLT文件中加入JS脚本,用户验证用户输入,收集表单数据,加载表单数据等。(这里涉及到JS代码和浏览器控件所在的winform窗体的代码的相互调用。)
1)首先把winform窗体的类加上这个属性[ComVisible(true)]
2) 在winform窗体里面写上public的方法
- //取得xml文件路径(供javascript调用)
- public string GetXMLPathForJava()
- {
- return tempxmlfilepath;
- }
复制代码3)在XSLT文件里面的JS代码中调用这个方法
- //调用c#方法获取xml文件路径
- var xmlfilepath = window.external.GetXMLPathForJava();
复制代码4)在XSLT文件中定义JS方法
- //数据保存
- function savetoxml()
- {
- }
复制代码5)在winform窗体中调用JS方法
//调用JS方法
- Object result = webBrowser1.Document.InvokeScript("savetoxml");
复制代码5.在显示页面的时候,我先使用下面的代码把XSLT和XML转换成HTML文件,存放在临时文件夹中,然后把浏览器控件的URL指向它。
- XslCompiledTransform transForm = new XslCompiledTransform();
- string xsltemplatepath = TemplateHelper.GetFactoryFormXSLTemplatePath(m_FileType, m_DataRow.xsl_version);
- try
- {
- transForm.Load(xsltemplatepath);
- transForm.Transform(tempxmlfilepath, temphtmlfilepath);
- }
- catch(Exception ex)
- {
- LogError.Write(ex.Message + "\n" + ex.StackTrace);
- MessageBox.Show("模板文件加载出错!");
- this.Close();
- return;
- }
- webBrowser1.Navigate(temphtmlfilepath);
复制代码6.在用户点击保存的时候,我通过XSLT中定义的JS代码,直接把用户保存的数据以XML的方式返回给winform的代码,然后保存到数据库中去。
- Object validateresult = webBrowser1.Document.InvokeScript("validate");
- if (Convert.ToBoolean(validateresult) == true)
- {
- Object result = webBrowser1.Document.InvokeScript("savetoxml");
- if (Convert.ToBoolean(result) == true)
- {
- this.Close();
- }
- else
- {
- MessageBox.Show("保存出错", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
- this.DialogResult = DialogResult.None;
- }
- }
- else
- {
- this.DialogResult = DialogResult.None;
- }
复制代码7.删除刚才产生的临时文件。