LoginSignup
26
22

More than 3 years have passed since last update.

Windows GUIプログラミング入門10 設定保存(1)

Last updated at Posted at 2017-03-21

■はじめに

今回は設定の保存/読み込みをやります。

キーワード:Settings, マルチユーザー設定, user.config, Local, Roaming, Style, 初期フォーカス, スタイル

[注意]
これまでの回で説明済みの操作方法等は、説明を省略したり簡略化している場合があります。

■開発環境

  • Windows 10
  • Visual Studio Community 2017
  • .NET Framework 4.x

■作ってみる

◇Grid分割、StackPanel配置

新規プロジェクトを作成したらGridを横に区切りましょう。
やり方を忘れた場合は第5回に戻りましょう。

wbg10-01.png

区切ったそれぞれの行にStackPanelをドラッグ&ドロップします。
wbg10-02.png

ドキュメントアウトラインでStackPanelCtrl + クリックで2つとも選択状態にし、右クリック「レイアウト」 - 「すべてリセット」を選択します。
wbg10-03.png

StackPanelが画面いっぱいに広がりました。
wbg10-04.png

下側のStackPanelOrientationHorizontalに、HorizontalAlignmentRightにします。
これで中に配置するコントロールが横並びかつ右寄せになります。
wbg10-05.png

◇ボタン配置、スタイル設定

ドキュメントアウトラインで下側のStackPanelを選択状態にし、Buttonを配置します。
wbg10-06.png

Gridの行高さの設定を変更します。
ドロップダウンからAutoを選択します。
wbg10-07.png

Windowタグのすぐ下にWindow.Resourcesタグを作り、Buttonのスタイルを定義します。
wbg10-08.png

ボタンのスタイル定義
<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Margin" Value="0,10,10,10"/>
        <Setter Property="Width" Value="100"/>
        <Setter Property="Height" Value="30"/>
    </Style>
</Window.Resources>

Buttonを1つ追加し、各種設定をします。
wbg10-09.png

ボタン定義
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
    <Button Content="ボタン"/>
    <Button x:Name="closeButton" Content="閉じる(_C)"/>
</StackPanel>

閉じるボタンの処理を書きます。

private void closeButton_Click(object sender, RoutedEventArgs e)
{
    this.Close();
}

◇入力項目配置、スタイル設定

ドキュメントアウトラインで上側のStackPanelを選択し、Label, TextBox, Label, TextBox, Label, ComboBoxの順に追加します。
wbg10-10.png

各種設定をします。

<StackPanel>
    <Label Content="名前(_N)"/>
    <TextBox x:Name="nameText" Text="トメ"/>
    <Label Content="歳(_A)"/>
    <TextBox x:Name="ageText" Text="88"/>
    <Label Content="血液型(_B)"/>
    <ComboBox x:Name="blood" Margin="5,0" Width="100" HorizontalAlignment="Left"/>
</StackPanel>

wbg10-11.png

Window.ResourcesLabelTextBoxのスタイル定義を追加します。
今度はx:Keyでスタイルの名前を付けます。

<Style x:Key="InputTitleStyle" TargetType="Label">
    <Setter Property="Margin" Value="5,15,5,0"/>
</Style>
<Style x:Key="InputTextStyle" TargetType="TextBox">
    <Setter Property="Margin" Value="5,0"/>
    <Setter Property="Width" Value="300"/>
    <Setter Property="HorizontalAlignment" Value="Left"/>
</Style>

利用する側はStyleプロパティで適用したいスタイルのKeyを指定します。

<Label Content="名前(_N)" Target="{Binding ElementName=nameText}" Style="{StaticResource InputTitleStyle}"/>
<TextBox x:Name="nameText" Text="トメ" Style="{StaticResource InputTextStyle}"/>
<Label Content="歳(_A)" Target="{Binding ElementName=ageText}" Style="{StaticResource InputTitleStyle}"/>
<TextBox x:Name="ageText" Text="88" Style="{StaticResource InputTextStyle}"/>
<Label Content="血液型(_B)" Target="{Binding ElementName=blood}" Style="{StaticResource InputTitleStyle}"/>

ComboBoxItemsプロパティ横の「...」からコレクションエディターを開き、ComboBoxItemを追加します。
wbg10-12.png

4つのComboBoxItemContentにそれぞれA, B, O, ABを設定します。
wbg10-13.png

<ComboBox x:Name="blood" Margin="5,0" Width="100" HorizontalAlignment="Left">
    <ComboBoxItem Content="A"/>
    <ComboBoxItem Content="B"/>
    <ComboBoxItem Content="O"/>
    <ComboBoxItem Content="AB"/>
</ComboBox>

画面起動時の最初のフォーカス位置を設定します。
wbg10-13_2.png

<Grid FocusManager.FocusedElement="{Binding ElementName=nameText}">

◇設定項目

ソリューションエクスプローラーでPropertiesの下のSettings.settingsをダブルクリックします。
wbg10-14.png

以下の表のように入力します。

名前 種類 スコープ
WindowTitle string アプリケーション 設定ファイルテスト
UserName string ユーザー
Age int ユーザー 0
Blood int ユーザー -1
ProfileConfig1 string ユーザー あああ

ProfileConfig1RoamingプロパティはTrueにします。
wbg10-15.png

アプリケーションスコープは、全ユーザーで共通的な固定値に使用します。
ユーザースコープは、ログインユーザー毎に保持する設定で使用します。
ユーザースコープは端末依存/非依存で2種類あります。
既定値はRoaming=Falseの端末依存です。

まとめると以下のようになります。

  • 全ユーザーで共通の固定値は、アプリケーションスコープにする。
  • ユーザー固有で端末に依存する設定(画面解像度や色数、ドライブ・フォルダパス等)は、ユーザースコープでRoamingFalseにする。
  • ユーザー固有で端末に依存しない設定は、ユーザースコープでRoamingTrueにする。
スコープ Roaming 読取専用 端末依存 ユーザー固有 保存先
アプリケーション False 〇〇〇.exe.config
ユーザー False Local\~\user.config
ユーザー True Roaming\~\user.config

設定読み込み/保存処理を書きます。
Windowのイベント、ContentRenderedに設定読み込み処理を、Closedに設定保存処理を書きます。
wbg10-16.png

private void Window_ContentRendered(object sender, EventArgs e)
{
    // 設定読み込み
    this.Title = Properties.Settings.Default.WindowTitle;
    nameText.Text = Properties.Settings.Default.UserName;
    ageText.Text = Properties.Settings.Default.Age.ToString();
    blood.SelectedIndex = Properties.Settings.Default.Blood;
}

private void Window_Closed(object sender, EventArgs e)
{
    // 設定保存
    Properties.Settings.Default.UserName = nameText.Text;
    Properties.Settings.Default.Age = int.Parse(ageText.Text);
    Properties.Settings.Default.Blood = blood.SelectedIndex;
    Properties.Settings.Default.Save();
}

閉じるボタンの左に配置したボタンのクリック処理を書きます。

private void Button_Click(object sender, RoutedEventArgs e)
{
    // 設定読み込み
    string config1 = Properties.Settings.Default.ProfileConfig1;
    // 表示
    MessageBox.Show(config1);
    // 設定更新
    Properties.Settings.Default.ProfileConfig1 = config1 + "a";
}

◇プロジェクトプロパティ設定

プロジェクトのプロパティで「アプリケーション」の「アセンブリ情報」ボタンを押します。
wbg10-30.png

「会社」の欄を入力します。
wbg10-31.png

ここではTestCompany1と入力しました。
wbg10-32.png

◇実行

Releaseビルドします。
wbg10-17.png

Releaseフォルダを開きます。
配布時は〇〇〇.exe〇〇〇.exe.configを渡してください。

exeを起動してみます。
wbg10-18.png

「ボタン」ボタンを押すとメッセージが表示されます。
テキストボックスを入力、コンボボックスを選択し、閉じるボタンで終了します。
ウィンドウが終了したのでconfigが更新されているはずです。
wbg10-19.png

exeと同じ場所にある〇〇〇.exe.configファイルは初期値で、ユーザー設定があればそちらが優先されます。
実行時にここの値が書き換わることはありません。

〇〇〇.exe.config(抜粋)
<userSettings>
    <WpfApp10.Properties.Settings>
        <setting name="UserName" serializeAs="String">
            <value />
        </setting>
        <setting name="Age" serializeAs="String">
            <value>0</value>
        </setting>
        <setting name="Blood" serializeAs="String">
            <value>-1</value>
        </setting>
        <setting name="ProfileConfig1" serializeAs="String">
            <value>あああ</value>
        </setting>
    </WpfApp10.Properties.Settings>
</userSettings>
<applicationSettings>
    <WpfApp10.Properties.Settings>
        <setting name="WindowTitle" serializeAs="String">
            <value>設定ファイルテスト</value>
        </setting>
    </WpfApp10.Properties.Settings>
</applicationSettings>

◇Localフォルダ

エクスプローラーで隠しファイルを表示するようにしておいて、ユーザー\【ユーザー名】\AppDataUsers\【ユーザー名】\AppData)フォルダを開きます。
Localフォルダ配下にはスコープ:ユーザー、Roaming:Falseの設定が、
Roamingフォルダ配下にはスコープ:ユーザー、Roaming:Trueの設定が格納されています。
wbg10-20.png

Local\【会社名】\【アプリ名.exe_長い文字列】\バージョン番号
(アセンブリ情報で「会社」を未入力の場合はLocal\【アプリ名】\【アプリ名.exe_長い文字列】\バージョン番号)フォルダにあるuser.config(ローカルユーザープロファイル)を開きます。
wbg10-21.png

画面で入力された内容で更新されています。

Localのuser.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <WpfApp10.Properties.Settings>
            <setting name="UserName" serializeAs="String">
                <value>なまえ★なまえ</value>
            </setting>
            <setting name="Age" serializeAs="String">
                <value>999</value>
            </setting>
            <setting name="Blood" serializeAs="String">
                <value>3</value>
            </setting>
        </WpfApp10.Properties.Settings>
    </userSettings>
</configuration>

◇Roamingフォルダ

Roaming\【会社名】\【アプリ名.exe_長い文字列】\バージョン番号
(アセンブリ情報で「会社」を未入力の場合はRoaming\【アプリ名】\【アプリ名.exe_長い文字列】\バージョン番号)フォルダにあるuser.config(移動ユーザープロファイル)を開きます。
wbg10-22.png

「ボタン」ボタンを押してメッセージを表示したので内容が更新されています。

Roamingのuser.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <WpfApp10.Properties.Settings>
            <setting name="ProfileConfig1" serializeAs="String">
                <value>あああa</value>
            </setting>
        </WpfApp10.Properties.Settings>
    </userSettings>
</configuration>

◇config読み込み

再度exeを起動してみます。
configの内容が復元されました。
wbg10-23.png

おしまい


<< 最初の記事   < 前の記事   次の記事 >

26
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
22