[C#.NET][Winform] 序列化表單 - 多國語言應用程式 / Form Serialize - Multiple Languages Application
利用序列化將表單上的設定儲存起來,本篇範例僅儲存控制項的Name及Text屬性,如此一來反序列化時再將其資料寫回控制項的Text屬性就能達到多語系的效果,以前也曾經寫過多國語系ttp://www.dotblogs.com.tw/yc421206/archive/2008/12/28/6553.aspx,當時是利用資源檔下去做處理,序列化方式請參考[.NET] 利用 泛型方法 重構 反序列化
建立資源檔時必需手動建立控制項的Name,相當累人
變更語系時還要特別的小心對應,若這時正在加班陷入精神恍神狀態,對應錯了就麻煩了,雖然不至於導致系統癱瘓,但錯誤終究發生機率還是很高。
在VB6時代裡常用的ini對應也是一樣要手動自己敲,相當的累人,在.NET世界的序列化,就是一個相當好用的方法,避掉了一些錯誤機會的發生。
實作序列化:
接下來實作一下表單序列化的方式
建立表單要存放的欄位,裡面的 ChildControls 是為了存放 Controls 中的控制項,若你的控制項是擺放在集合控制項內,必須另外把它們撈出來。
public class FormFields { public string Name; public string Text; public List<FormFields> ChildControls = new List<FormFields>(); public FormFields() { } public FormFields(Control Ctrl) { Name = Ctrl.Name; Text = Ctrl.Text; } }
然後再建立一個FormSerialize類別,
Serialize方法:將表單內所有控制項的Name及Text屬性儲存下來。
SerializeControl方法:找出所有控制項並加入ChildControls集合內。
Deserializez方法:打開檔案依控制項Name還原Text屬性。
DeserializeControl方法:找出所有控制項並還原屬性。
public class FormSerialize { public void Serialize(string File, Control root) { FormFields field = new FormFields(root); SerializeControl(field, root); XmlSerializer xml = new XmlSerializer(typeof(FormFields)); TextWriter writer = new StreamWriter(File); try { xml.Serialize(writer, field); } finally { writer.Close(); } } //遞迴找出所有控制項,加入至集合 private void SerializeControl(FormFields Field, Control Ctrl) { foreach (Control ctrl in Ctrl.Controls) { FormFields field = new FormFields(ctrl); Field.ChildControls.Add(field); if (ctrl.Controls.Count > 0) SerializeControl(field, ctrl); } } public void Deserialize(string File, Control Ctrl) { XmlSerializer xml = new XmlSerializer(typeof(FormFields)); FileStream fs = new FileStream(File, FileMode.Open); FormFields field = null; try { var o = xml.Deserialize(fs); if (o != null) field = (FormFields)o; } finally { fs.Close(); } //Form if (Ctrl.Name == field.Name) Ctrl.Text = field.Text; DeserializeControl(field, Ctrl); } //遞迴找出所有控制項,並指定Text屬性 private void DeserializeControl(FormFields Field, Control Ctrl) { if (Field == null) return; //Form.Controls foreach (FormFields field in Field.ChildControls) { if (Ctrl.Controls[field.Name] != null) { Ctrl.Controls[field.Name].Text = field.Text; if (field.ChildControls.Count > 0) DeserializeControl(field, Ctrl.Controls[field.Name]); } } } }
操作方式:
短短幾行程式碼變可以達到序列化/反序號表單,這是序列化相當實用的一種方法,接下來看看如何操作,
1.設計好一個表單,這時的Text屬性都是中文(或英文)
2.呼叫序列化方法FormSerialize.Serialize,儲存表單的資訊。
private void btnSerialize_Click(object sender, EventArgs e) { this._Serialize.Serialize(Cht, this);//序列化中文版 }
3.此時會產生一個中文版的檔案,將它複製一份→變更檔名,然後將內容裡的中文改成英文。
英文版
4.語系建立好後,呼叫FormSerialize.Dserialize方法計可以切換語系了,用戶端呼叫完整範例
const string Cht = "resource_ch.xml"; const string Eng = "resource_eng.xml"; FormSerialize _Serialize = new FormSerialize(); private void btnSerialize_Click(object sender, EventArgs e) { this._Serialize.Serialize(Cht, this);//序列化中文版 } private void btnCht_Click(object sender, EventArgs e) { if (!File.Exists(Cht)) return; this._Serialize.Deserialize(Cht, this); } private void btnEng_Click(object sender, EventArgs e) { if (!File.Exists(Eng)) return; this._Serialize.Deserialize(Eng, this); }
觀察一下反序列化xml檔的變數,變數o可以看到xml結構跟我們定義的 FormFields 是一樣的
後記:
序列化表單真的是儲存設定檔的一個好選擇,如果你有許多的控制項參數需要定義,這樣的做法真的可以省掉對應的時間,比如在groupBox1控制項裡有一大堆的textBox需要儲存,若用以往的方法來處理相當的累人,由其是增加或減少攔位,若靈活的運用序列化,必然可以節省掉相當多的時間的,不彷考慮下次在您的專案這樣處理吧。FormSerialize.zip
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET