使用WMFL实现可配置Windows窗体

原创 2004年07月22日 09:41:00
 

使用WMFL实现可配置Windows窗体

 

         作者: Joe Stegman

翻译:秋枫

原文出处:http://windowsforms.net/articles/wfml.aspx

文章原名: Using the Windows Forms XML Parser Sample

代码下载:下载

Introduction

这里介绍的是个带有可以扩展机制的例子,通过添加一个标记模型来实现。我们把里面的解析规则可以概述为“XML 元素映射到.NET Framework 类型 XML 中的属性映射到类型的属性、方法(或者事件)”。这个例子包含一个markup parser通过解析XML文件来动态的产生一个对象的实例树。对于标记的格式包括下面的结构:

1.   XML 命名空间 .NET Framework 命名空间的映射

2.   对象实例化名称

3.   对象验证及引用

4.   属性设置

5.   实例和静态方法

6.   事件委托

7.   组件引用

 

Disclaimer

这个例子中使用的技术不是下一版本Windows Forms的一部分。另外,这里的例子是针对.NET Framework version 1.1的,至于其他版本没有测试过。

Basic Sample

下面的例子显示了一个XML的语法用来声明或定义一个包含了Label的简单窗体。

xml version="1.0" encoding="utf-8" ?>

mapping xmlns="http://www.microsoft.com/2003/WindowsForms"

          namespace="System.Windows.Forms;System.Drawing"?>

<wfml xmlns="http://www.microsoft.com/2003/WindowsForms"

      xmlns:wfml="http://www.microsoft.com/2003/WFML"> 

  <Form wfml:root="true" Text="Basic Sample" Size="300,200">

    <Label Text="Hello World" AutoSize="True" Location="10, 20"/>

    <method.Show/>

  Form>

wfml>

WMFL解析器根据上面的XML文件来动态的生成一个窗体。这里假设上面的XML文件内容包含在“basic.xml”文件中。

MarkupParser parser = new MarkupParser();

object form = parser.Parse("basic.xml");

下面是动态生成的窗体:


Dissecting the Basic Sample

根据Xml文档中的定义,解析器进行了精确的处理,一个根标签,实体声明和一个结束标签。下面是对各部分的描述。

XML Declaration

xml version="1.0" encoding="utf-8" ?>

这行定义了XML针对这个例子的默认命名空间同时定义了元素和属性的前缀。

Instance Declarations

<Form wfml:root="true" Text="Basic Sample" Size="300,200">

    <Label Text="Hello World" AutoSize="True" Location="10,20"/>

    <method.Show/>

  Form>

当处理xml的时候,解析器将通过默认构造函数创建一个窗体的实例,同时设置Text属性为“Basic Sample,Size属性为“300200”。解析器还创建了一个Label实例添加到窗体的Controls集合,同时设置了LabelText属性为“Hello World”,设置他的AutoSize属性为“True”,Location属性为“10,20”。最后,解析器还调用了Show方法来显示窗体的实例。

XML Namespace to .NET Framework Mappings

解析器通过

标签来创建System.Windows.Forms.Form类的一个实例。.NET Framework 1.1版本至少包含两个不同的“Form”类型:一个是在System.Windows.Forms命名空间,另一个是在System.Web.UI.MobileControls。解析器通过Xml文件中的命名空间映射来选择需要创建的实例的命名空间,在这个例子中,元素使用默认的命名空间。而这里默认的为http://www.microsoft.com/2003/WindowsForms:

<wfml xmlns="http://www.microsoft.com/2003/WindowsForms" …

这里的映射就是指示Xml namespaceSystem.Windows.Forms .NET Framework 命名空间:

mapping xmlns="http://www.microsoft.com/2003/WindowsForms"

          namespace="System.Windows.Forms;System.Drawing"?>

解析器通过这个映射来选择Form的类型命名空间为System.Windows.Forms而不是System.Web.UI.MobileControls”.

Collection Heuristics

当解析器遇到元素的子元素时,就会根据上面定义的映射规则来生成相对应的类的实例加入到父控件的一个容器(如果父控件是一个容器,就直接添加)。在默认的情况下,解析器寻找一个“Controls”集合但是也可以把子控件通过“.”符号加载到的不同的集合。

<MenuItem Text="New" >

  <property.MenuItems>

    <MenuItem Text="Window" Shortcut="CtrlN" />

    <MenuItem Text="-" />

    <MenuItem Text="Message" />

    <MenuItem Text="Post" />

    <MenuItem Text="Contact" />

    <MenuItem Text="Internet Call" />

  property.MenuItems>

MenuItem>

在上面的例子中,那些子菜单被明确的加入到父一级的MenuItem的“MenuItems”集合中。对于“property.PropertyName”符号在下面的Markup reference一节中会有更多的详细说明。

 

Markup Reference

这个简单的解析器使用一些的属性,元素和一些其他符号指令来处理转换。那些属性和元素在http://www.microsoft.com/2003/WFML命名空间下,同时使用“wfml”作为前缀。

wfml:ID Attribute

这个ID属性用来唯一表示元素的实例。另外,解析器还提供一个API通过ID来查询一个实例,在下面的例子中,Form元素被给了“form1”。

xml version="1.0" encoding="utf-8" ?>

mapping xmlns="http://www.microsoft.com/2003/WindowsForms"

          namespace="System.Windows.Forms;System.Drawing"?>

<wfml xmlns="http://www.microsoft.com/2003/WindowsForms"

      xmlns:wfml="http://www.microsoft.com/2003/WFML"> 

  <Form wfml:ID="form1" Text="Basic Sample" Size="300,200">

   <Label Text="Hello World" AutoSize="True" Location="10, 20"/>

    <method.Show/>

  Form>

wfml>

解析器能通过“Find”方法来重新获取“form1”实例。

MarkupParser parser = new MarkupParser();

Parser.Parse(“basic.xml”);

Form form1 =(Form)parser.Find(“form1”);

wfml:root Attribute

root属性标识由解析器的“Parser”方法生成的实例。整个Xml只能有一个元素使用root属性。下面的例子中“form1元素包含了“root”属性。

xml version="1.0" encoding="utf-8" ?>

mapping xmlns="http://www.microsoft.com/2003/WindowsForms"

          namespace="System.Windows.Forms;System.Drawing"?>

<wfml xmlns="http://www.microsoft.com/2003/WindowsForms"

      xmlns:wfml="http://www.microsoft.com/2003/WFML"> 

  <Form wfml:ID="form1" wfml:root="true" Text="Basic Sample" Size="300,200">

    <Label Text="Hello World" AutoSize="True" Location="10, 20"/>

    <method.Show/>

  Form>

wfml>

下面是“Parse”方法返回一个“form1”实例:

MarkupParser parser = new Markupparser();

Form form1 = (Form)parser.Parse(“basic.xml”);

wfml:argument Attribute

当实例化类型的时侯,解析器使用类型的默认构造函数。但是有些类型没有默认的构造函数,比如Bitmap

Argument属性专门为没有默认构造函数的类型传递一个参数。下面的例子就是为Bitmap的构造函数传递一个“c:/image.jpg”参数。

<Form wfml:root="true" wfml:ID="form1" Name="Form1" Text="Set Background"> 

  <property.BackgroundImage>

    <Bitmap wfml:argument="C://image.jpg"/>

  property.BackgroundImage>

  <method.Show/>

Form>

注意这里如果是使用带多个参数的构造函数是不可能的。

property Element

解析器的通常规则是xml元素映射到类型而xml属性映射到类型的属性。

<Element Attribute="string value"/>

解析器能通过TypeConverters(System.ComponentModel.TypeConverter)来有效的处理字符串到非字符串属性的转换。举例Form类的BackColor属性是“System.Drawing.Color”类型的,但是可以使用下面的设置:

<Form BackColor="Green"/>

在上面的例子中,BackColor属性是通过一个TypeConverter来把“Green”字符串转换成“System.Drawing.Color”得到的。在一般情况下TypeCoverter模块可以很正常的工作,但是在处理复杂的属性类型时(比如Image)不会提供一个很好的结果。解析器通过使用一个“.”属性符号来处理更多复杂属性的设置,下面使用就是设置窗体的BackgroundImage

<Form wfml:root="true" wfml:ID="form1" Name="Form1" Text="Set Background"> 

  <property.BackgroundImage>

    <Bitmap wfml:argument="C://image.jpg"/>

  property.BackgroundImage>

  <method.Show/>

Form>

在上面的例子中,把Bitmap实例作为窗体的BackgroundImage设置。

method Element

类似于上面的“.”属性符号,解析支持“.”方法符号。当解析器发现一个元素带有“method.methodName”,他将会在父元素实例中调用“methodName”方法。下面就会在“form1”实例中调用“Show”方法。

<Form wfml:root="true" wfml:ID="form1" Name="Form1" Text="Set Background"> 

  <property.BackgroundImage>

    <Bitmap wfml:argument="C://image.jpg"/>

  property.BackgroundImage>

  <method.Show/>

Form>

解析器能调用实例或静态函数,但是不能调用含有多个参数的方法。下面的例子是调用带有一个参数的静态方法:

<Form wfml:root="true" wfml:ID="form1" Name="Form1" Text="Set Background"> 

  <property.BackgroundImage>

    <method.FromFile Static="System.Drawing.Image">

      C://image.jpg

    method.FromFile>

  property.BackgroundImage>

  <method.Show/>

Form>

上面调用静态方法“System.Drawing.Image.FromFile”,参数为“c:/image.jpg”。窗体的的BackgroundImage属性值为静态方法的返回值。

wfml:var Element

解析器对创建引用类型的变量提供了有限的支持。任何属性使用wfml:ID 属性能被解析为引用类型。如下:

<Form wfml:ID="form1" Name="Form1" Text="Simple"/>

<wfml:var Name="form1">

  <method.Show/>

wfml:var>

在上面的例子中,“wfml:var”元素引用“form1”参数也就是窗体,“Show”方法在“form1”的实例中被调用。

Variable Prefix

以“$”开始的属性值被处理为是引用参数。

<wfml:var wfml:ID="image">

 <method.FromFile Static="System.Drawing.Image">C://image.jpgmethod.FromFile>

wfml:var>

<Form BackgroundImage="$image" Name="Form1" Text="Set Background"> 

  <method.Show/>

Form>

Mapping Processing Instruction

通常的使用语法是:

mapping xmlns="XMLNamespace" namespace=".NET Namespaces"?>

.NET Framework命名空间属性可以包含一个或多个用“;”隔开的列表。

mapping xmlns="MyNamespace" namespace="System.Windows.Forms;System.Drawing"?>

在实例化类型的时侯,解析器将会映射Xml元素中指定的“xmlns”到.NET Framework类型。

Assembly Processing Instruction

对于“assembly”的处理指令是通过添加装配件引用。

assembly name="system.data" version="1.0.5000.0" culture="neutral" PublicKeyToken="b77a5c561934e089"?>

Markup Parser Reference

解析器根据Xml文件动态的生成一个实例树,而他的API描述如下:

Parse 方法使用一个字符串参数或者一个TextReader作为参数。该方法返回的一个实例是文档里那个包含了“wfml:root”的属性的元素的ID值,或者就是第一个元素。

AddVariable Method

下面的例子将产生一个窗体同时包装窗体的Load事件:

<Form wfml:root="true" Load="me.FormLoadHandler" Text="Load Sample"/> 

解析器会认出“Load”是一个事件并寻找一个“me”的变量同时把窗体的Load事件用“me’s”的FormLoadHandler委托来包装。

private void button1_Click(object sender, System.EventArgs e)

{

  MarkupParser  parser = new MarkupParser();

  // Add "this"

  parser.AddVariable("me", this);

  // Parse

  object    obj = parser.Parse("sample.xml");

}

 

private void FormLoadHandler(object sender, EventArgs e)

{

  MessageBox.Show("Form Load");

}

Find Method

Find方法被用来从变量上下文中重新获得一个实例(wfml:ID)。举例,下面的例子定义了一个“form1窗体,里面包含了一个“button1按钮:

<Form wfml:root="true" wfml:ID="form1" Text="Find Sample"> 

  <Button wfml:ID="button1"/>

Form>

通过Find方法能够重新得到“button1”的实例:

private void button1_Click(object sender, System.EventArgs e)

{

  MarkupParser  parser = new MarkupParser();

  // Parse (returns form1)

  object    obj = parser.Parse("sample.xml");

  // Get button1 instance

  Button    button1 = parser.Find("button1") as Button;

}

Reset Method

解析器的变量上下文(变量列表)是跨多个解析器实例共享的(静态列表)。

Reset方法就是用来清空这个共享变量列表。

Status Event

解析器的状态事件提供每一行的解析信息。注意这个事件只有在调试场景下才有用。

windows from 窗体登录

从app.config文件中获取节点的name属性为strcondeconnectionString的值,也就是获取对应的连接字符串 ConfigurationManager.string st...
  • tlljhj
  • tlljhj
  • 2012-02-20 21:03:23
  • 334

C++中关于windows窗体的编程

C++,windows窗体编程,MFC,API
  • zhangrrrr
  • zhangrrrr
  • 2017-03-23 10:01:47
  • 343

使用windows窗体应用程序来实现用户名与密码的登录

使用windows窗体应用程序来实现用户名与密码的登录。在本页面项目下右击选择添加一个新建项选取基于服务器的数据库,弹出的页面取消。本页面左侧会出现服务器资源管理器建表,进行一系列操作。连接数据库时也...
  • wang_yuanyuan1
  • wang_yuanyuan1
  • 2012-02-20 21:12:41
  • 3277

Windows窗体与控件

学习下Window的窗体与控件,UI,我的IDE是VS2012,通过学习这些基本控件,如果以后要用到别的控件,就能够较快上手。 Windows窗体窗体是应用程序的基本单元,是非常重要的。它实质上是一块...
  • im_zhq
  • im_zhq
  • 2016-05-11 11:20:39
  • 4924

SpringMVC利用Quartz实现可配置的定时器

  • 2015年04月22日 20:36
  • 20.65MB
  • 下载

图表可配置展示功能

  • 2017年06月14日 23:35
  • 1.01MB
  • 下载

使用quartz+spring实现简单的可配置化的定时任务(可和数据库配套使用)

首先定义一个job要实现Job接口,以后各种各样的任务都放在这个job中执行: import org.quartz.Job; import org.quartz.JobDataMap; import...
  • IOpfan
  • IOpfan
  • 2016-06-07 11:28:40
  • 1149

如何设计一个基于Lotus的可配置的工作流

 要实现流程的“可配置”,即相当于由用户自己“组建”流程,那么,对于程序的开发者,要做的事自然就是一个相反的过程(“拆解”流程)。考虑如何拆解流程能使用户重新组建时省力省心,实际上就是设计一个好用的、...
  • freefly
  • freefly
  • 2009-03-11 19:39:00
  • 2692

vs2008 使用c#编写web浏览器加载的windows窗体控件

在过去,Web程序员经常在他们的Web程序中使用ActiveX控件来实现一些胖客户端才具有的功能。不过现在开发者可 以很容易的通过Microsoft.NET Framework来简洁和安全的建立对象...
  • lz576825608
  • lz576825608
  • 2012-08-28 23:20:27
  • 3124

C#窗体修改密码的代码

  • 2010年06月13日 18:51
  • 25KB
  • 下载
收藏助手
不良信息举报
您举报文章:使用WMFL实现可配置Windows窗体
举报原因:
原因补充:

(最多只允许输入30个字)