2008年11月22日 星期六

DynamicProperties動態屬性設定1-3

RunPC 109期:在.Net上保存應用程式設定(一)
(2) 如何在專案中設定非預設的動態屬性設定(自訂的動態屬性設定)
在Form1表單屬性視窗上點DynamicProperties下之Advanced出現如圖六之對話盒,其列表皆為預設的動態屬性,所以我們在屬性視窗中與該對話盒內比對找尋沒有對應的屬性來成為這節的例子,恰好我們找到屬性視窗中有Location屬性,而Dynamic Properties對話盒沒有該設定視窗位址的選項,就讓我們舉Location屬性為非預設的動態屬性的例子,步驟如下:

(圖六)


1. 於app.config內輸入:

< key="Form1.X" value="10">
< key="Form1.Y" value="10">
儲存,代表設定表單於瑩幕上的位址。
註:Location屬性內由X,Y所組成,表示表單Form1左上角點,是故該例子以保存表單的X,Y值(“Form1.X;Form1.Y)為例。

2. 於Sub New程序內模擬InitializeComponent內的作法利用AppSettingsReader類別來讀取設定檔的內容值;宣告x,y為整數,利用AppSettingsReader的GetValue方法,傳入二參數一為key值("Form1.X","Form1.Y")另一為傳回值所屬的資料型態為System.Int32再將資料型態轉為整數Integer,最後將表單的位置移至(x,y)這點上。

Dim MyConfigReader As System.Configuration.AppSettingsReader=New system.Configuration.AppSettingsReader()
Dim x,y As Integer
x = CType(MyConfigReader.GetValue("Form1.X",GetType(System.Int32)), Integer)
y = CType(MyConfigReader.GetValue("Form1.Y",GetType(System.Int32)), Integer)
Me.Location = New System.Drawing.Point(x, y)

注意:因為InitializeComponent是系統所產生的程序,不允許被修改。
3. 執行後卻發現未能如預期的將表單移置(x,y)這點上,甚至呈現的位置也都沒有改變,那是因為未將將StartPosition改為Manual,將StartPosition改為Manual再次執行,表單就可以移置正確的位置上。

這段我們模擬系統所產生的程式碼,來完成我們自訂動態屬性部分,重點是在如何利用AppSettingsReader類別來取得設定檔案的設定值,接下來讓我們思考當所開發的系統安裝後,使用者使用時我們總不可能請他手動去更改設定檔案部分,那該怎樣可以在系統執行時期時,提供如VS.Net IDE環境設定 (圖七) 般的使用者介面(UI)給使用者來設定,以防手動設定上造成不可預期的錯誤,這正是下面所要討論的。


(圖七)

(3) 如何在執行時期保留動態屬性值
此處我們會說明怎樣用.Net所提供的System.Xml名稱空間下的相關類別來維護XML(即app.config)的資料,及使用System.Reflection來找到設定檔的位置。
讓我們延續上面的例子使它可以在執行時期,保存視窗目前的位置(X,Y),待下次再次載入表單時,可以取回上次保存後的設定值,以便設定視窗位置。
1. 使用者介面:在表單上建立二個Label(Label1、Label2)、二個TextBox(txtX、txtY)來呈現目前視窗的位置、二按鈕(CmdSet、CmdSave),當按下CmdSet按鈕時來設定視窗位置;而當按下CmdSave時儲存視窗目前位置至設定檔案中, Label1、Label2的Text屬性分別設X:和Y:。
2. 在Sub New程序中之Me.Location = New System.Drawing.Point(x, y)下加入:

txtX.Text = CType(x, System.String)
txtY.Text = CType(y, System.String)

取得目前視窗啟動所在位置。
3. 於CmdSet_Click事件中加入以下程式碼,用來立即設定視窗位置。

Dim X, Y As Integer
X = CType(txtX.Text, System.Int32)
Y = CType(txtY.Text, System.Int32)
Me.Location = New System.Drawing.Point(x, y)

4. 於Form1_Move事件中加入以下程式碼,在視窗位置移動時txtX、txtY立即顯示視窗所在位置。

txtX.Text = CType(Me.Location.X, System.String)
txtY.Text = CType(Me.Location.Y, System.String)

5. 於CmdSave_Click事件中撰寫儲存目前位置至設定檔中。
利用Reflection來找設定檔的位置

Dim RA As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly
Dim StrCnfgPath As String = RA.Location & ".config"
Dim XmlDoc As New System.Xml.XmlDocument()
XmlDoc.Load(StrCnfgPath)
Dim AddNode As System.Xml.XmlNode
For Each AddNode In XmlDoc.Item("configuration").Item("appSettings")
If AddNode.Name = "add" Then
Select Case AddNode.Attributes.GetNamedItem("key").Value
Case "Form1.X"
AddNode.Attributes.GetNamedItem("value").Value = CType(Me.Location.X, System.String)
Case "Form1.Y"
AddNode.Attributes.GetNamedItem("value").Value = CType(Me.Location.Y, System.String)
End Select
End If
Next
XmlDoc.Save(StrCnfgPath)

RA.Location取得目前執行檔案的位置,而再加上".config"即前面說的佈署時設定檔的位置,而非開發時期用的app.config設定檔案。再來利用.Net操控XML的XmlDocument類別載入設定檔(StrCnfgPath),再找出每個在"configuration"下"appSettings"的節點,判斷節點的名稱是否為"add",如果是的話比較該節點的"key"值是否為"Form1.X"或"Form1.Y"(當然也可以是其它您所設定的key值),再將目前表單的位置存回它對應"key"的"value"值,最後存回設定檔中,即可完成儲存設定的動作。
註:在本例VS.Net IDE中按F5執行,儲存目前所在位置(X,Y),停下重新執行是否發現並未如預期的將設定值儲存下來呢?可別太快下結論以為這是系統Debug還是程式有謬誤喔!那是因為在開發環境中每次執行時會將app.config內容蓋回我們儲存的設定檔內,而我們在上面程式碼所抓取的StrCnfgPath卻是『執行檔名.exe.config』而非app.config設定檔案,是故只要在佈署時就不會有此問題。

結論:
這篇文章中讓我們體驗到微軟在VS.Net IDE內的一個體貼的設計(DynamicProperties),甚至讓我們不用撰寫一行程式碼就可以輕鬆設定預設的動態屬性,完成早期需要繁雜程序才可完成的動作,而自訂的動態屬性設定只要模擬學習系統產生的程式碼,即可以輕易完成設定,最後我們談到怎麼在執行時期保留動態屬性值,讓使用者可以簡易的完成保存應用程式設定值,而不至於要手動修改設定檔案。其中我們也說明了開發時期的app.config設定檔與佈署安裝的『執行檔名.exe.config』設定檔案的關係,希望該篇文章對讀者有所幫助。我們預計於下一篇文章中為各位介紹如何在.Net中更彈性的保存應用程式設定值,怎麼利用.Net上XML相關物件來操控自訂的XML設定檔案,如表(一)中選項配分中的階層關係……等,而非只是Key與Value的成對關係。

沒有留言:

加入書籤: MyShare HemiDemi Baidu Google Bookmarks Yahoo! My Web PChome Del.icio.us Digg technorati furludn bookmark 其他更多書籤

BOOKS:New and Upcoming