最近Windows Store Appsを少々勉強中ですが、当たり前にできるだろうよ思われることができなかったり、こんなことまでできるの?ってことがあったりいろいろ苦労しています。今回はWindows Store Appsの様々なサンプルアプリに入っているSuspensionManagerクラスのSaveAsync()時に発生するエラーを回避する方法を紹介します。
SuspensionManagerはアプリがSuspension状態に入るとき、アプリのページ状態の保存を手伝うクラスです。ページ状態を保存したあと、アプリの次回の起動時に終了前の状態を復元するために使います。FrameクラスのNavigateメソッドでページ移動を行うとき、パラメータなしでページクラスタイプだけを指定して移動する場合、SuspensionManagerは正常にページ状態を保存してくれます。
問題は、Navigateメソッドにページタイプ以外にパラメータを指定する場合に発生します。パラメータにintやbool,stringなどWindowsRTの基本データ型を指定するときは問題ありませんが、自作のクラスや配列(例えばobject[])など、複雑なデータ型を指定するとSuspensionManagerのSaveAsync()メソッドの途中にエラーが発生します。これを解決するためにSuspensionManagerを修正して複雑なデータ形を保存できるようにする方法もありますが、私はデフォルトのデータやクラスはなるべく修正しないで使う方を好みますので、逆に複雑なデータ形をWindowsRTの基本データ型に変換する方法を使います。
- パラメータとして渡すクラスを自作する。クラスは[DataContract]のAttributeをつけておきます。またクラス内の保存する変数にすべて[DataMember]Attributeをつけます。これをつけておかないとその変数はシリアライズされません。
- 1のクラスをXML形式のstringにシリアライズし、FrameのNavigateのパラメータとして渡します。
- 移動先のページからstring型で渡されたパラメータを元のクラスに復元します。
1の自作クラスの部分は省略し、2,3のXML形式のstringにシリアライズ、デシリアライズするコードを紹介します。
public static string ToXMLText(NaviParameter obj) { DataContractSerializer serializer = new DataContractSerializer(typeof(NaviParameter)); using (MemoryStream memoryStream = new MemoryStream()) using(StreamReader reader = new StreamReader(memoryStream)) { StringWriter sw = new StringWriter(); serializer.WriteObject(memoryStream, obj); memoryStream.Seek(0, SeekOrigin.Begin); string text = reader.ReadToEnd(); return text; } }
public static NaviParameter FromXMLText(string xmlText) { DataContractSerializer serializer = new DataContractSerializer(typeof(NaviParameter)); using (StringReader stringReader = new StringReader(xmlText)) using (XmlReader xmlReader = XmlReader.Create(stringReader)) { return (NaviParameter)serializer.ReadObject(xmlReader); } }
私の場合、ページ移動のパラメータがあんまり種類がなかったので直接型を指定していますが、ジェネリックパターンを利用するのもいいと思います。
参考にしたページ:Jsonを利用したパラメータの文字列化
1件のコメント