明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

使用WMFL完成可設(shè)置Windows窗體

[摘要]使用WMFL實(shí)現(xiàn)可配置Windows窗體 作者: Joe Stegman翻譯:秋楓原文出處:http://windowsforms.net/articles/wfml.aspx文章...
使用WMFL實(shí)現(xiàn)可配置Windows窗體



作者: Joe Stegman

翻譯:秋楓

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

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

代碼下載:下載

Introduction

這里介紹的是個(gè)帶有可以擴(kuò)展機(jī)制的例子,通過(guò)添加一個(gè)標(biāo)記模型來(lái)實(shí)現(xiàn)。我們把里面的解析規(guī)則可以概述為“XML 元素映射到.NET Framework 類型 而XML 中的屬性映射到類型的屬性、方法(或者事件)”。這個(gè)例子包含一個(gè)markup parser通過(guò)解析XML文件來(lái)動(dòng)態(tài)的產(chǎn)生一個(gè)對(duì)象的實(shí)例樹(shù)。對(duì)于標(biāo)記的格式包括下面的結(jié)構(gòu):

1. XML 命名空間 到 .NET Framework 命名空間的映射

2. 對(duì)象實(shí)例化名稱

3. 對(duì)象驗(yàn)證及引用

4. 屬性設(shè)置

5. 實(shí)例和靜態(tài)方法

6. 事件委托

7. 組件引用



Disclaimer

這個(gè)例子中使用的技術(shù)不是下一版本W(wǎng)indows Forms的一部分。另外,這里的例子是針對(duì).NET Framework version 1.1的,至于其他版本沒(méi)有測(cè)試過(guò)。

Basic Sample

下面的例子顯示了一個(gè)XML的語(yǔ)法用來(lái)聲明或定義一個(gè)包含了Label的簡(jiǎn)單窗體。

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解析器根據(jù)上面的XML文件來(lái)動(dòng)態(tài)的生成一個(gè)窗體。這里假設(shè)上面的XML文件內(nèi)容包含在“basic.xml”文件中。

MarkupParser parser = new MarkupParser();

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

下面是動(dòng)態(tài)生成的窗體:



Dissecting the Basic Sample

根據(jù)Xml文檔中的定義,解析器進(jìn)行了精確的處理,一個(gè)根標(biāo)簽,實(shí)體聲明和一個(gè)結(jié)束標(biāo)簽。下面是對(duì)各部分的描述。

XML Declaration

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

這行定義了XML針對(duì)這個(gè)例子的默認(rèn)命名空間同時(shí)定義了元素和屬性的前綴。

Instance Declarations

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

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

<method.Show/>

Form>

當(dāng)處理xml的時(shí)候,解析器將通過(guò)默認(rèn)構(gòu)造函數(shù)創(chuàng)建一個(gè)窗體的實(shí)例,同時(shí)設(shè)置Text屬性為“Basic Sample”,Size屬性為“300,200”。解析器還創(chuàng)建了一個(gè)Label實(shí)例添加到窗體的Controls集合,同時(shí)設(shè)置了Label的Text屬性為“Hello World”,設(shè)置他的AutoSize屬性為“True”,Location屬性為“10,20”。最后,解析器還調(diào)用了Show方法來(lái)顯示窗體的實(shí)例。

XML Namespace to .NET Framework Mappings

解析器通過(guò) 標(biāo)簽來(lái)創(chuàng)建System.Windows.Forms.Form類的一個(gè)實(shí)例。.NET Framework 1.1版本至少包含兩個(gè)不同的“Form”類型:一個(gè)是在System.Windows.Forms命名空間,另一個(gè)是在System.Web.UI.MobileControls。解析器通過(guò)Xml文件中的命名空間映射來(lái)選擇需要?jiǎng)?chuàng)建的實(shí)例的命名空間,在這個(gè)例子中,元素使用默認(rèn)的命名空間。而這里默認(rèn)的為http://www.microsoft.com/2003/WindowsForms:

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

這里的“映射”就是指示Xml namespace到System.Windows.Forms .NET Framework 命名空間:

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

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

解析器通過(guò)這個(gè)映射來(lái)選擇Form的類型命名空間為System.Windows.Forms而不是System.Web.UI.MobileControls”.

Collection Heuristics

當(dāng)解析器遇到元素的子元素時(shí),就會(huì)根據(jù)上面定義的映射規(guī)則來(lái)生成相對(duì)應(yīng)的類的實(shí)例加入到父控件的一個(gè)容器(如果父控件是一個(gè)容器,就直接添加)。在默認(rèn)的情況下,解析器尋找一個(gè)“Controls”集合但是也可以把子控件通過(guò)“.”符號(hào)加載到的不同的集合。

<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>

在上面的例子中,那些子菜單被明確的加入到父一級(jí)的MenuItem的“MenuItems”集合中。對(duì)于“property.PropertyName”符號(hào)在下面的Markup reference一節(jié)中會(huì)有更多的詳細(xì)說(shuō)明。



Markup Reference

這個(gè)簡(jiǎn)單的解析器使用一些的屬性,元素和一些其他符號(hào)指令來(lái)處理轉(zhuǎn)換。那些屬性和元素在http://www.microsoft.com/2003/WFML命名空間下,同時(shí)使用“wfml”作為前綴。

wfml:ID Attribute

這個(gè)ID屬性用來(lái)唯一表示元素的實(shí)例。另外,解析器還提供一個(gè)API通過(guò)ID來(lái)查詢一個(gè)實(shí)例,在下面的例子中,F(xiàn)orm元素被給了“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>

解析器能通過(guò)“Find”方法來(lái)重新獲取“form1”實(shí)例。

MarkupParser parser = new MarkupParser();

Parser.Parse(“basic.xml”);

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

wfml:root Attribute

root屬性標(biāo)識(shí)由解析器的“Parser”方法生成的實(shí)例。整個(gè)Xml只能有一個(gè)元素使用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”方法返回一個(gè)“form1”實(shí)例:

MarkupParser parser = new Markupparser();

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

wfml:argument Attribute

當(dāng)實(shí)例化類型的時(shí)侯,解析器使用類型的默認(rèn)構(gòu)造函數(shù)。但是有些類型沒(méi)有默認(rèn)的構(gòu)造函數(shù),比如Bitmap。

Argument屬性專門為沒(méi)有默認(rèn)構(gòu)造函數(shù)的類型傳遞一個(gè)參數(shù)。下面的例子就是為Bitmap的構(gòu)造函數(shù)傳遞一個(gè)“c:\image.jpg”參數(shù)。

<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>

注意這里如果是使用帶多個(gè)參數(shù)的構(gòu)造函數(shù)是不可能的。

property Element

解析器的通常規(guī)則是xml元素映射到類型而xml屬性映射到類型的屬性。

<Element Attribute="string value"/>

解析器能通過(guò)TypeConverters(System.ComponentModel.TypeConverter)來(lái)有效的處理字符串到非字符串屬性的轉(zhuǎn)換。舉例Form類的BackColor屬性是“System.Drawing.Color”類型的,但是可以使用下面的設(shè)置:

<Form BackColor="Green"/>

在上面的例子中,BackColor屬性是通過(guò)一個(gè)TypeConverter來(lái)把“Green”字符串轉(zhuǎn)換成“System.Drawing.Color”得到的。在一般情況下TypeCoverter模塊可以很正常的工作,但是在處理復(fù)雜的屬性類型時(shí)(比如Image)不會(huì)提供一個(gè)很好的結(jié)果。解析器通過(guò)使用一個(gè)“.”屬性符號(hào)來(lái)處理更多復(fù)雜屬性的設(shè)置,下面使用就是設(shè)置窗體的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實(shí)例作為窗體的BackgroundImage設(shè)置。

method Element

類似于上面的“.”屬性符號(hào),解析支持“.”方法符號(hào)。當(dāng)解析器發(fā)現(xiàn)一個(gè)元素帶有“method.methodName”,他將會(huì)在父元素實(shí)例中調(diào)用“methodName”方法。下面就會(huì)在“form1”實(shí)例中調(diào)用“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>

解析器能調(diào)用實(shí)例或靜態(tài)函數(shù),但是不能調(diào)用含有多個(gè)參數(shù)的方法。下面的例子是調(diào)用帶有一個(gè)參數(shù)的靜態(tài)方法:

<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>

上面調(diào)用靜態(tài)方法“System.Drawing.Image.FromFile”,參數(shù)為“c:\image.jpg”。窗體的的BackgroundImage屬性值為靜態(tài)方法的返回值。

wfml:var Element

解析器對(duì)創(chuàng)建引用類型的變量提供了有限的支持。任何屬性使用wfml:ID 屬性能被解析為引用類型。如下:

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

<wfml:var Name="form1">

<method.Show/>

wfml:var>

在上面的例子中,“wfml:var”元素引用“form1”參數(shù)也就是窗體,“Show”方法在“form1”的實(shí)例中被調(diào)用。

Variable Prefix

以“$”開(kāi)始的屬性值被處理為是引用參數(shù)。

<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

通常的使用語(yǔ)法是:

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

.NET Framework命名空間屬性可以包含一個(gè)或多個(gè)用“;”隔開(kāi)的列表。

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

在實(shí)例化類型的時(shí)侯,解析器將會(huì)映射Xml元素中指定的“xmlns”到.NET Framework類型。

Assembly Processing Instruction

對(duì)于“assembly”的處理指令是通過(guò)添加裝配件引用。

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

Markup Parser Reference

解析器根據(jù)Xml文件動(dòng)態(tài)的生成一個(gè)實(shí)例樹(shù),而他的API描述如下:

Parse 方法使用一個(gè)字符串參數(shù)或者一個(gè)TextReader作為參數(shù)。該方法返回的一個(gè)實(shí)例是文檔里那個(gè)包含了“wfml:root”的屬性的元素的ID值,或者就是第一個(gè)元素。

AddVariable Method

下面的例子將產(chǎn)生一個(gè)窗體同時(shí)包裝窗體的Load事件:

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

解析器會(huì)認(rèn)出“Load”是一個(gè)事件并尋找一個(gè)“me”的變量同時(shí)把窗體的Load事件用“me’s”的FormLoadHandler委托來(lái)包裝。

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方法被用來(lái)從變量上下文中重新獲得一個(gè)實(shí)例(wfml:ID)。舉例,下面的例子定義了一個(gè)“form1”窗體,里面包含了一個(gè)“button1”按鈕:

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

<Button wfml:ID="button1"/>

Form>

通過(guò)Find方法能夠重新得到“button1”的實(shí)例:

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

解析器的變量上下文(變量列表)是跨多個(gè)解析器實(shí)例共享的(靜態(tài)列表)。

Reset方法就是用來(lái)清空這個(gè)共享變量列表。

Status Event

解析器的狀態(tài)事件提供每一行的解析信息。注意這個(gè)事件只有在調(diào)試場(chǎng)景下才有用。