設定ダイアログというと、一番簡単に使えるのはタブを使ったダイアログですが、.NETフレームワークのタブコントロールは、WindowsXPのビジュアルスタイルに(完全には)対応していません。
まあ、C言語のダイアログあたりだと割と当たり前のようなので、その辺は仕方ないと諦めればいいのでしょうが、それでは何となく不満です。そこで、WindowsXPでも不自然のないダイアログを作ってみたいと思います。
さて、WindowsXPでも不自然のないダイアログとなるとタブコントロールは使えません。ですから最近OperaやFireFoxなどの設定ダイアログでよく見かける、リストボックスタイプの設定ダイアログになります。
そうなると問題なのは、どうやって設定項目を作るか ですね。Panelを順次表示するのも良いですが、(IDE上での)編集が面倒です、Delphiなどだと、タブページに"TabVisible"プロパティがあるので、タブコントロールで設定項目を作り、TabVisibleをいじれば解決するのですが…。
そこで出てくるのが、UserControlです。これは、Delphiで言うのならばフレームのように、いくつかのコントロールを乗っけて、あたかも一つのコントロールのように扱えるものです。これを作成して、フォームのサイズに合わせ、リストから呼び出せば完成です。
設定パネル共通のインターフェース
まずは、下準備として設定用パネル(UserControl)すべてに共通の関数を定義します。ベース用のコントロールを継承して作っても良いですが、それをするとSharpDevelopではデザインが出来なくなってしまいますので、インターフェースです。
とりあえず、わたしはおんぷ村のうらにある、MemXMLFile(配布されてるバージョンにはバグがあります、ごめんなさい、今度修正版アップします)を使いますから、
public interface ISaveControl { void LoadControl(Chie.Ini.MemXMLFile xml); void SaveControl(Chie.Ini.MemXMLFile xml); }
とします。
ユーザーコントロールの作成
次に、ユーザーコントロールを作成します。複数のページを作るときは、Sizeを合わせて置いてください。DockやAnchorを駆使するのも悪くないかも知れません(未確認)。
このユーザーコントロールで必要なのは、ISaveControlを実装することと、ToStringをオーバーライドすることだけ。
ToStringについては他の方法でも良いですが、リストボックスに設定内容(キャプション)を表示するために、ToStringを使います、これだと、リストボックスにコントロールを追加するだけで文字列が表示されます。
コンフィグダイアログ(ベース)の作成
最後にメインのダイアログを作成します。必要なコントロールは
- リストボックス
- パネル(ユーザーコントロール格納用)
- OKボタン、キャンセルボタン
だけ。パネルは不可欠ではありませんが、ユーザーコントロールの座標を簡単に決定できるので置いておくと良いでしょう。
そして、フォームのコンストラクタで、リストボックスにユーザーコントロールを追加します。
configList.Items.Add(new WindowsSetting()); configList.Items.Add(new ExtSetting()); configList.Items.Add(new ToolSetting()); configList.SelectedIndex = 0;
で、フォームのロード(別にこのすぐ下でも良いですが)時に、全アイテムのISaveControl.LoadControlを呼び出します。
Chie.Ini.MemXMLFile xml = new Chie.Ini.MemXMLFile(Constant.SettingFile); foreach(UserControl control in configList.Items) { ISaveControl save = (ISaveControl)control; save.LoadControl(xml); }
OKボタンが押されたときには、ISaveControl.SaveControl やり方は上と同じです。
Chie.Ini.MemXMLFile xml = new Chie.Ini.MemXMLFile(Constant.SettingFile); foreach(UserControl control in configList.Items) { ISaveControl save = (ISaveControl)control; save.SaveControl(xml); } xml.UpdateFile();
最後の仕上げに、リストボックスのアイテム選択に応答するために、リストボックスのSelectedIndexChangedイベントで
configPanel.Controls.Clear(); UserControl control = ((UserControl)configList.SelectedItem); configPanel.Controls.Add(control); control.Location = new Point(0, 0);
とします。ここで最初に設置したPanelの出番です。Panelを用意することで、座標をnew Point(0, 0);とするだけで設定できます。Dock.Fillでも良いですね。
と、以上で完成です。呼び出す側は普通にShowModalで呼び出すだけです。近いうちにおんぷ村のうらにでもおきたいですね。