WPF グラフィックスオブジェクトのシリアル化

Last Updated 2012/12/15


このページでは 2 つのテーマを扱います。一つは、WPF グラフィックスオブジェクトのシリアル化、もう一つは XML ドキュメント形式の初期化ファイルを扱うクラスです。


アプリケーションを作っていると、アプリケーションの設定条件をどこかに記録しておいて、次に起動するときに条件を読み込んで再現するという作業が必要です。これをシリアル化と呼びます。正確に言うと、オブジェクトの内容を記録可能な形式に変換することをシリアル化 (serialize)、そのデータを読み込んで元のオブジェクトとして再構築することを逆シリアル化 (deserialize) と呼びます。これらの両方の手続きを総称して通常はシリアル化と呼びます。

さて、シリアル化の対象はいろいろあると思いますが、ここでは WPF グラフィックスオブジェクト、特に、Brush オブジェクトを対象として説明します。まず、基本的な機能をメソッドの形式で示します。

// 指定の WPF オブジェクトをシリアル化する
// obj : シリアル化するオブジェクト
// 戻り値は、シリアル化後の XML ドキュメント形式の文字列
private string Serialize(object obj)
{
  var settings = new XmlWriterSettings();

  // 出力時の条件
  settings.Indent = true;
  settings.NewLineOnAttributes = false;

  // XML バージョン情報の出力を抑制する
  // バージョン情報が必要な場合は ConformanceLevel.Document を指定する
  settings.ConformanceLevel = ConformanceLevel.Fragment;

  var sb = new StringBuilder();
  XmlWriter writer = null;
  XamlDesignerSerializationManager manager = null;

  try
  {
    writer = XmlWriter.Create(sb, settings);
    manager = new XamlDesignerSerializationManager(writer);
    manager.XamlWriterMode = XamlWriterMode.Expression;
    System.Windows.Markup.XamlWriter.Save(obj, manager);
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
  finally
  {
    if (writer != null)
      writer.Close();
  }

  return sb.ToString();
}

//---------------------------------------------------------------------------------------------
// 指定の XML 文を読み込んで逆シリアル化し、WPF オブジェクトを返す
// xmlText : XML 文
// 戻り値  : WPF オブジェクト
private object Deserialize(string xmlText)
{
  var doc = new XmlDocument();

  try
  {
    doc.LoadXml(xmlText);
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }

  object obj = null;

  try
  {
    obj = System.Windows.Markup.XamlReader.Load(new XmlNodeReader(doc));
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }

  return obj;
}

次のような XAML 構文があるとして、上記のメソッドを使ってシリアル化してみましょう。

<Rectangle Name="rect" Width="200" Height="100" Stroke="Blue" StrokeThickness="1" Margin="10">
  <Rectangle.Fill>
    <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
      <GradientStop Color="Red" Offset="0" />
      <GradientStop Color="Blue" Offset="1" />
    </LinearGradientBrush>
  </Rectangle.Fill>
</Rectangle>

上記の Serialize メソッドは以下のコードで呼び出します。

string s = emanual.Wpf.Utility.WpfObjectSerializer.Serialize(rect.Fill);

Serialize メソッドの呼び出し結果の文字列は次のとおりです。

<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <LinearGradientBrush.GradientStops>
    <GradientStop Color="#FFFF0000" Offset="0" />
    <GradientStop Color="#FF0000FF" Offset="1" />
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

次に、逆シリアル化です。Serialize メソッドを使ってシリアル化したテキストを引数として Deserialize メソッドを呼び出します。

  rect2.Fill = (LinearGradientBrush)emanual.Wpf.Utility.WpfObjectSerializer.Deserialize(xmlText);

シリアル化に関係する機能は WpfObjectSerializer クラスとしてまとめましたので、コードの全体はこのクラスをご覧ください。なお、このクラスはグラフィックスオブジェクトに限らず、XAML 構文で表現可能なオブジェクトをシリアル化できます。ためしに、Window オブジェクトをシリアル化してみてください。


XmlIni クラス

XmlIni クラスは、XML 構文を使う初期化ファイルを操作するクラスです。クラスの概要は「WPF 対応カスタムコントロール」-「XML 形式の初期化ファイル」を参照してください。


シリアル化のサンプルプロジェクト

WpfObjectSerializer クラスと XmlIni クラスの使い方を示すサンプルプロジェクトを Visual Studio 2010 C# / WPFで作成しました。フリーウエアです。ソーソコードの改変・流用も可能です。

SerializeBrush.zip (22,945 bytes)

−以上−