ユーザー設定カラクリ編とヒント(アプリケーション設定 その2)

あんまり深くないカラクリ解説編。
まずはFormから値がどこにどう設定されているのかってあたり。Form1.Designer.csを開いてみてみると、Properties.Settings.Defaultにデータがバインドされてるのが分かる。
データバインディングでLocationが変わるたびに何かコードがごそごそ動くのは無駄すぎて嫌って場合は、デザイナ画面の(PropertyBinding)での設定を行わず、プロジェクトのプロパティの設定画面でデータの定義だけを行い、データの設定と読み取りだけをコードで実現することもできる。FormのOnLoadで

try
{
	this.Location = Properties.Settings.Default.FormLocation;
}
catch ( ConfigurationErrorsException )
{
}

として読み取り、OnClosingで

Properties.Settings settings = Properties.Settings.Default;
settings.FormLocation = this.Location;
try
{
	settings.Save();
}
catch ( ConfigurationErrorsException ce )
{
	MessageBox.Show( ce.BareMessage, "Error!" );
}
finally
{
	base.OnClosing( e );
}

として書き込めばOK。
デザイナでの設定は楽だけど使いづらい面もあって、ちょっとしたアプリ程度なら使えるが、こった事をしたい場合は使えないと思ったほうがよい。例えば、永続化する設定値に、アプリケーション設定の属性を独自に定義することができないようだ。こういうときはデザイナ画面での設定をあきらめ、手でコードを書くしかないようだ(それでもSave()なんて書けるのでユーザー設定を使うメリットは大きい)。

次にユーザー設定ファイルの場所。ClickOnceかWinFormかどうか、ローミングプロファイルを使ってるかどうか、デバッグ時はvshost有効かどうか、などによって変わってくる。AssemblyInfo.csのCompany名、バージョン設定もファイル位置にかかわる。詳しくはこのへん。WinFormで特に設定もしないと「Documents and Settings\username\Local Settings\Application Data」の下にできた(ローミングなし)。ファイル名はuser.config。
user.configファイルはバージョンごとにフォルダが作られ、ファイルが変わる。AssemblyInfo.csでバージョンが時間で変わるようにしていると(最後の桁が*とか)、開発時にはなんともうっとうしい。
プロジェクトのプロパティを開いて「設定」を見るとアプリケーション設定が見れる。その1の例ならFormLocationだけが表示される。この画面の左上にある「同期」を押すと、古い設定ファイルをいっぺんに削除できる。でも、AssemblyInfo.csでCompanyが入っていないと見つけれないっぽい。
さらに、同期の右にある「コードの表示」を押すと、Settings.csというファイルが生成される!Settings.csは「設定の検証」にある、設定値の検証用コードの雛形になっている。設定値の検証を行うことができるタイミングは4つ。ロード時、セーブ時、値変更前、値変更後。最低でもロード時は必ず検証が必要だ。user.configはXMLなので、エディタなどで簡単に値を変更できる。範囲外の値に書き換えられてたら、デフォルト値に変更するなどのコードがどうしても必要になる。SettingChangingで検証するなら、すべての変更時に呼ばれるようなので、その他のタイミングでの検証は不要になる。
Settings.csはSettings.Designer.csのpartialになっている。Settings.Designer.csは「アプリケーション設定のアーキテクチャ」にある、設定の定義相当。プロジェクトのプロパティの設定画面で値を追加すると、このファイルとapp.configファイルに追加分が書き込まれる。
逆にapp.configに設定を手書きで追加すると、プロジェクトのプロパティの設定とSettings.Designer.csに自動的に取り込まれる!なので、デザイナでユーザー設定を追加した場合、手書きで値を追加するのがものすごく困難になる。というか、どうやったら両方で共存できるのか分からない...。一つでも手書きによる追加が必要になったら、すべて手書きするしかないのかも...。(こっちにやり方を書いた)

手書きするにも、デザイナで生成されたコードが参考になるので、一度デザイナに生成させたコードを見てみると早い。MSDN「方法 : アプリケーション設定を作成する」は、突然SettingsやappSettingsなんてのが出てきて混乱する。単純ミスだろうけど。このドキュメントの前にデザイナのコードを読んだほうがいい。

ユーザー設定を記録するようにすると、バージョンが変わった際の設定値の取り扱いが問題になってくる。旧バージョンの設定はばっさり切り捨てるってのもありだけど(^^;、できるものだけでも引き継ぎたいところ。Upgrade()として古い設定を読み取る仕組みは用意されている。Upgrade()に関するヒントは「LocalFileSettingsProvider.Upgrade」や「ApplicationSettingsBase.Upgrade」あたりが参考になる。

とりあえずこのあたりまで調べたので記録。
(追記)ちょっとはしょってたところを追加。
(さらに追記)OnClosingのコード修正。前のでも問題ない。
(さらにさらに追記)例外捕捉処理を追加。