やりたいこと
WPFのアプリにて、例えばアプリの「設定画面」などでユーザーが設定した内容を、簡単に保存/読み出ししたい。
自前でファイルに書き出して保存し、それを読み出すこともできるとは思うが、めんどくさいのでもっと簡単にやりたい。
今回のやり方
VisualStudioの「プロジェクトデザイナーの設定ページ」というものを使う。
(→こちら参照)
ソリューションエクスプローラーの「Setting.setting」を開くか、
プロジェクトのプロパティの中の「設定」を選択すると、「設定値」を設定するための画面が開く。
とりあえず上記のように4つの項目を作成して、それぞれの「名前」「種類」「値」をセットする。
※スコープを「アプリケーション」にすると、その設定項目は読み取り専用となる。この画面で値をセットはできるが、プログラム動作中に書き換えたりできなくなるため、今回の目的では使えない。(アプリの設定を一括して持たせておく目的には便利)
そうすると、下記のような書き方で、設定を読み書きすることができる。
// MySetting1はstring型
string str = Properties.Settings.Default.MySetting1;
// MySetting2はint型
Properties.Settings.Default.MySetting1 = 123;
Properties.Settings.Default.Save();
読み込みは、Properties.Settings.Default.設定名
で読める。
書き込みは、その設定名に書き込んだあと、Properties.Settings.Default.Save();
を行う。
Save()をすると、その後アプリを一度終了して再度起動したときも、Saveした値を覚えている。
※一つ書き込むたびにSaveせずに、いろいろな設定を全部設定し終わった後にSave()すると、設定した値をすべて一括にSaveできる。
これを利用すると、アプリの設定画面でユーザーが入力した設定を、次回起動時に復元する、ということが実現できる。
実験のためのサンプルコード
設定の実験のために、サンプルを作成した。下のように、各種設定とコード記述を行う。
■動作時画面
実験のため、下記のような動作をさせる。
- 起動時、Setting.settingに設定した値(4つ)を、画面表示する。
- テキストboxの横のボタンを押すと、各設定を保存する。
■アプリケーション設定・アセンブリ設定
■Setting.setting
■画面コード(xaml)
<Window x:Class="DefaultNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp30"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBox Name="txt1" Grid.Row="0"/>
<TextBox Name="txt2" Grid.Row="1"/>
<TextBox Name="txt3" Grid.Row="2"/>
<TextBox Name="txt4" Grid.Row="3"/>
<Button Name="bt1" Grid.Row="0" Grid.Column="1" Content="string" Click="bt1_Click"/>
<Button Name="bt2" Grid.Row="1" Grid.Column="1" Content="int" Click="bt2_Click"/>
<Button Name="bt3" Grid.Row="2" Grid.Column="1" Content="bool" Click="bt3_Click"/>
<Button Name="bt4" Grid.Row="3" Grid.Column="1" Content="double" Click="bt4_Click"/>
</Grid>
</Window>
■画面コード(cs)
using System.Windows;
namespace DefaultNamespace
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
//設定値を読み書きするためのプロパティを作成
private string MyString
{
get { return Properties.Settings.Default.MySetting1; }
set { Properties.Settings.Default.MySetting1 = value; }
}
private int MyInt
{
get { return Properties.Settings.Default.MySetting2; }
set { Properties.Settings.Default.MySetting2 = value; }
}
private bool MyBool
{
get { return Properties.Settings.Default.MySetting3; }
set { Properties.Settings.Default.MySetting3 = value; }
}
private double MyDouble
{
get { return Properties.Settings.Default.MySetting4; }
set { Properties.Settings.Default.MySetting4 = value; }
}
// 起動時に設定の値を読み込み、画面表示
public MainWindow()
{
InitializeComponent();
txt1.Text = MyString;
txt2.Text = MyInt.ToString();
txt3.Text = MyBool.ToString();
txt4.Text = MyDouble.ToString();
}
// 画面に入力した値を保存する
private void bt1_Click(object sender, RoutedEventArgs e)
{
MyString = txt1.Text;
Properties.Settings.Default.Save();
}
private void bt2_Click(object sender, RoutedEventArgs e)
{
MyInt = int.Parse(txt2.Text);
Properties.Settings.Default.Save();
}
private void bt3_Click(object sender, RoutedEventArgs e)
{
MyBool = bool.Parse(txt3.Text);
Properties.Settings.Default.Save();
}
private void bt4_Click(object sender, RoutedEventArgs e)
{
MyDouble = double.Parse(txt4.Text);
Properties.Settings.Default.Save();
}
}
}
Save()したものはどこに保存されている?
下記に、user.configファイルとして保存されている。
■ファイルパス
C:\Users\<ユーザー名>\AppData\Local\<会社名>\<アプリ名>.exe_Url_<ハッシュ値>\<バージョン>\user.config
■ファイルの内容
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings">
<section name="DefaultNamespace.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<DefaultNamespace.Properties.Settings>
<setting name="MySetting1" serializeAs="String">
<value>DEF</value>
</setting>
<setting name="MySetting3" serializeAs="String">
<value>True</value>
</setting>
<setting name="MySetting2" serializeAs="String">
<value>10</value>
</setting>
<setting name="MySetting4" serializeAs="String">
<value>999.3</value>
</setting>
</DefaultNamespace.Properties.Settings>
</userSettings>
</configuration>
■ファイルの動き
アプリ起動時やSave()で保存したときの動きを見る限り、下記のような動作をしている。
- アプリの初回起動時は、そのパスにファイルは存在しない。(フォルダも存在してない)
- ファイルがないときは、画面で設定した初期値が使われる。(user.config)削除すると、初期値にもどる。
- 最初に
Properties.Settings.Default.Save();
を実行したときに、ファイル、フォルダができる。 - user.configの中には、すべての設定項目があるわけではない。
- 値が代入された設定値だけ、ファイルに保存される。(もちろん代入した後にSave()された時だけファイルに保存される)
- ファイル内に値の記述がない設定値は、初期値扱いになる。
- 元の値と同じ値を代入後Saveしたときも、ファイルに保存される。
■注意
アプリ(exe)のバージョンが上がると、user.configファイルの保存場所が変わる。
例えばバージョンが「1.2.3.4」から「1.2.3.5」に上がったとすると、
C:\Users\<ユーザー名>\AppData\Local\CompanyName\AssemblyName.exe_Url_offobezk1v5z2srsyclwkbtlysxbum4f\1.2.3.4\user.config
から
C:\Users\<ユーザー名>\AppData\Local\CompanyName\AssemblyName.exe_Url_offobezk1v5z2srsyclwkbtlysxbum4f\1.2.3.5\user.config
に変わる。
そのため、
このやり方では、**「ソフトのバージョンが上がった場合にもユーザーの設定を引き継ぎたい」**という要求は実現することができない。要注意。
参考
Settings page, Project Designer(msdocsのページ)
https://docs.microsoft.com/ja-jp/visualstudio/ide/reference/settings-page-project-designer?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DJA-JP%26k%3Dk(ApplicationSettingsOverview);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.7)%26rd%3Dtrue&view=vs-2019