6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【WPF】画面の状態や、入力値を保存、復元(読込)したい [Persistence Framework]

Last updated at Posted at 2019-03-26

はじめに

デスクトップアプリケーションで、画面の入力値や、状態を全て復元したい場面があるかと思います。
そんな時、Infragistics社製のPersistence Frameworkは、とても柔軟に保存および復元が可能です。
Persistence Frameworkは、各コントロール型毎に保存対象のプロパティを設定できたり、グループ化してまとめて処理したり等、柔軟に保存/読込を行う事が可能です。もちろん、WPF標準のコントロールだけではなく、カスタムコントロールのプロパティも自在に保存、復元(読込)ができます。

アプリケーションサンプル

サンプルアプリケーションを用意しました。
デフォルトのコントロールを配置し、保存ボタンで入力値を保存、読込ボタンで保存時の状態を復元します。
Capture.gif

サンプルコード

GitHub
https://github.com/furugen/wpf-samples-persistence

MainWindow.xaml
<Window x:Class="PersistenceSample.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:PersistenceSample"
        xmlns:ig="http://schemas.infragistics.com/xaml"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" x:Name="leftMenuArea"></ColumnDefinition>
            <ColumnDefinition Width="10"></ColumnDefinition>
            <ColumnDefinition Width="80*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        
        <ListView x:Name="listView" Grid.Row="0" Grid.Column="0" >
            <ListViewItem>
                <TextBlock>AAA</TextBlock>
            </ListViewItem>
            <ListViewItem>
                <TextBlock>BBB</TextBlock>
            </ListViewItem>
            <ListViewItem>
                <TextBlock>CCC</TextBlock>
            </ListViewItem>
        </ListView>

        <GridSplitter Grid.Column="1" Width="10" HorizontalAlignment="Center" />

        <Grid Grid.Row="0" Grid.Column="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <StackPanel Grid.Column="0">
                <StackPanel Orientation="Horizontal" Margin="10">
                    <TextBlock Width="100">コンボボックス</TextBlock>
                    <ComboBox x:Name="comboBox" Width="200">
                        
                        <ComboBoxItem>C1</ComboBoxItem>
                        <ComboBoxItem>C2</ComboBoxItem>
                        <ComboBoxItem>C3</ComboBoxItem>
                    </ComboBox>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="10">
                    <TextBlock Width="100">テキストボックス</TextBlock>
                    <TextBox  x:Name="textBox"  Width="200">
                    </TextBox>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="10">
                    <TextBlock Width="100">デートピッカー</TextBlock>
                    <DatePicker Width="200" x:Name="datePicker" />
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="10">
                    <TextBlock Width="100">ラジオボタン</TextBlock>
                    <RadioButton x:Name="radioOnAttached" GroupName="TestRaadio" Content="添付あり"/>
                    <RadioButton x:Name="radioNonAttached" IsChecked="True"  GroupName="TestRaadio" Content="添付なし"/>
                </StackPanel>
                <StackPanel Orientation="Horizontal" Margin="10">
                    <TextBlock Width="100">チェックボックス</TextBlock>
                    <CheckBox x:Name="checkBox"  Content="完了済"/>
                </StackPanel>
            </StackPanel>

        </Grid>
        

        <StackPanel Grid.Row="1" Grid.ColumnSpan="3">
            <Button Margin="5" Click="BtnSaveClick">保存</Button>
            <Button Margin="5" Click="BtnLoadClick">読込</Button>
            <Button Margin="5" Click="BtnClearClick">入力値クリア(お試し用)</Button>
        </StackPanel>

    </Grid>
</Window>
MainWindow.xaml.cs
   /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        // 保存対象のコントロールグループ
        private PersistenceGroup taregetGroup = new PersistenceGroup();
        // 保存内容のMemoryStream
        private MemoryStream saveMemoryStrem;


        public MainWindow()
        {
            InitializeComponent();

            // 保存対象のプロパティやコントロールの設定などを行う。
            SettingSaveTargetControls();
        }

        private void BtnSaveClick(object sender, RoutedEventArgs e)
        {
            saveMemoryStrem = PersistenceManager.Save(taregetGroup);
            MessageBox.Show("保存しました。");
        }

        private void BtnLoadClick(object sender, RoutedEventArgs e)
        {
            saveMemoryStrem.Position = 0;
            if (saveMemoryStrem != null)
            {
                PersistenceManager.Load(taregetGroup, saveMemoryStrem);
                MessageBox.Show("読み込みました。");
            }
        }

        private void SettingSaveTargetControls()
        {
            // 保存対象のコントロールに対し、保存するプロパティを設定する。
            this.SetSettingsControl(this.comboBox);
            this.SetSettingsControl(this.textBox);
            this.SetSettingsControl(this.datePicker);
            this.SetSettingsControl(this.radioOnAttached);
            this.SetSettingsControl(this.radioNonAttached);
            this.SetSettingsControl(this.checkBox);
            this.SetSettingsControl(this.listView);

            // 保存対象のコントロールを1つのグループとして登録。
            PersistenceManager.SetPersistenceGroup(this.comboBox, taregetGroup);
            PersistenceManager.SetPersistenceGroup(this.textBox, taregetGroup);
            PersistenceManager.SetPersistenceGroup(this.datePicker, taregetGroup);
            PersistenceManager.SetPersistenceGroup(this.radioOnAttached, taregetGroup);
            PersistenceManager.SetPersistenceGroup(this.radioNonAttached, taregetGroup);
            PersistenceManager.SetPersistenceGroup(this.checkBox, taregetGroup);
            PersistenceManager.SetPersistenceGroup(this.listView, taregetGroup);

        }

        private void SetSettingsControl(DependencyObject target)
        {
            PersistenceSettings setting = new PersistenceSettings();
            setting.SavePersistenceOptions = Infragistics.Persistence.Primitives.PersistenceOption.OnlySpecified;

            // コントロールにより保存対象のプロパティを決定する。
            if (target is ComboBox)
            {
                setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "SelectedIndex" });
            }
            else if (target is TextBox)
            {
                setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "Text" });
            }
            else if (target is DatePicker)
            {
                setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "SelectedDate" });
            }
            else if (target is RadioButton)
            {
                setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "IsChecked" });
            }
            else if (target is CheckBox)
            {
                setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "IsChecked" });
            }
            else if (target is ListView)
            {
                setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "SelectedIndex" });
            }
            PersistenceManager.SetSettings(target, setting);
        }

        private void BtnClearClick(object sender, RoutedEventArgs e)
        {
            this.comboBox.SelectedIndex = -1;
            this.textBox.Text = null;
            this.datePicker.SelectedDate = null;
            this.radioOnAttached.IsChecked = true;
            this.radioNonAttached.IsChecked = true;
            this.checkBox.IsChecked = false;
            this.listView.SelectedIndex = -1;
        }
    }

サンプルコードの解説

保存処理

保存対象のコントロールのグループ化

保存対象のコントロールをグループ(PersistenceGroup)として登録することでグループ単位で処理が可能となり、後続でまとめての処理が行いやすいのため、まずはグループ登録します。

PersistenceGroup taregetGroup = new PersistenceGroup();

// 保存対象のコントロールを1つのグループとして登録。
PersistenceManager.SetPersistenceGroup(this.comboBox, taregetGroup);
PersistenceManager.SetPersistenceGroup(this.textBox, taregetGroup);
PersistenceManager.SetPersistenceGroup(this.datePicker, taregetGroup);
PersistenceManager.SetPersistenceGroup(this.radioOnAttached, taregetGroup);
PersistenceManager.SetPersistenceGroup(this.radioNonAttached, taregetGroup);
PersistenceManager.SetPersistenceGroup(this.checkBox, taregetGroup);
PersistenceManager.SetPersistenceGroup(this.listView, taregetGroup);

上記のようにグループ化してあげれば、グループ単位での保存、読込が可能となります。

// 保存処理
saveMemoryStrem = PersistenceManager.Save(taregetGroup);
// 読込処理
PersistenceManager.Load(taregetGroup, saveMemoryStrem);

各コントロールの保存プロパティの設定

コントロールの型毎に保存対象のプロパティを設定しています。たとえば、TextBoxであれば、Textプロパティを対象にしています。

if (target is TextBox)
{
     setting.PropertySettings.Add(new PropertyNamePersistenceInfo() { PropertyName = "Text" });
}

このように対象のコントロール毎に柔軟にプロパティの設定ができるので、標準コントロールだけではなく、カスタムコントロールなどの指定も簡単にできます。また、今回は入力値を保存対象プロパティに指定してますが、Width,Heightといった外観に関わるプロパティも指定可能です。

読込処理

グループ化している状態であれば、PersistenceGroupと保存内容のMemortyStreamをPersistenceManagerに渡してあげればOK。

PersistenceManager.Load(taregetGroup, saveMemoryStrem);

保存形式

今回はStreamでの取り扱いでしたが、XML形式での保存も対応しています。

まとめ

入力値の保存や復元を簡単にするPersistence Frameworkの紹介でしたが如何でしょうか。
柔軟に様々なコントロールの保存や読込に対応。データベースだけではなく、ローカルファイルへの保存もできますのでデータベースでの管理までは必要ないけど、ユーザーの登録値は保存したい!という場面などにもご利用いただけます!

6
6
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
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?