はじめに
デスクトップアプリケーションで、画面の入力値や、状態を全て復元したい場面があるかと思います。
そんな時、Infragistics社製のPersistence Frameworkは、とても柔軟に保存および復元が可能です。
Persistence Frameworkは、各コントロール型毎に保存対象のプロパティを設定できたり、グループ化してまとめて処理したり等、柔軟に保存/読込を行う事が可能です。もちろん、WPF標準のコントロールだけではなく、カスタムコントロールのプロパティも自在に保存、復元(読込)ができます。
アプリケーションサンプル
サンプルアプリケーションを用意しました。
デフォルトのコントロールを配置し、保存ボタンで入力値を保存、読込ボタンで保存時の状態を復元します。
サンプルコード
GitHub
https://github.com/furugen/wpf-samples-persistence
<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>
/// <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の紹介でしたが如何でしょうか。
柔軟に様々なコントロールの保存や読込に対応。データベースだけではなく、ローカルファイルへの保存もできますのでデータベースでの管理までは必要ないけど、ユーザーの登録値は保存したい!という場面などにもご利用いただけます!