使用WMFL實現可配置Windows窗體

 

使用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/>

  < span>Form>

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

  < span>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" />

  < span>property.MenuItems>

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

  < span>Form>

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

  < span>Form>

< span>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"/>

  < span>property.BackgroundImage>

  <method.Show/>

< span>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"/>

  < span>property.BackgroundImage>

  <method.Show/>

< span>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"/>

  < span>property.BackgroundImage>

  <method.Show/>

< span>Form>

解析器能調用實例或靜態函數,但是不能調用含有多個參數的方法。下面的例子是調用帶有一個參數的靜態方法:

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

  <property.BackgroundImage>

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

      C://image.jpg

    < span>method.FromFile>

  < span>property.BackgroundImage>

  <method.Show/>

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

< span>wfml:var>

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

Variable Prefix

以“$”開始的屬性值被處理爲是引用參數。

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

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

< span>wfml:var>

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

  <method.Show/>

< span>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"/>

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

解析器的狀態事件提供每一行的解析信息。注意這個事件只有在調試場景下才有用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章