読者です 読者をやめる 読者になる 読者になる

Kikuchy's Second Memory

つくる楽しさをもっと伝えたい。プログラムを書いていて、わからなかったこと・気付いた事を書き留めています。

Frame.Navigation(sourcePageType, parameter) に渡すparameterの値の種類

ついこの前躓いたので、メモ。

Metro Style Applicationでは、Frameの中にページを読み込むことができます。
遷移先のページ(SomePage)になにがしかのパラメーター(param)を渡したいときには、

rootFrame.Navigate(typeof(SomePage), param);

このように記述します。詳しくはこちらのMSDNのページをご参照。
Frame.Navigate(TypeName, Object) method

上記のMSDNのサイトには、

public bool Navigate(
  Type sourcePageType, 
  object parameter
)

と書かれています。
一見、paramにはobjectならば何でも渡せそうです。

実際に、渡すことができます。
が、自作のクラスなどを渡してしまうと、アプリケーションがSuspendedになった時に例外が発生してしまうのです。


実は、parameterに指定する値は、 int や string などのプリミティプな型である必要があります


原因は、アプリケーションがSuspendedになったとき、アプリケーションは、ページに渡されたパラメーターをXMLファイルにシリアライズして保存することにあります。
プリミティブな型でないと、SuspentionManagerが「保存できない」と怒り出すのでした。



あれ、では二つ以上のパラメーターを与えたいときはどうすれば…?
これまでは

public class SomePageParam {
    public string p1;
    public int p2;
}

とかってクラスを作って与えていました。
しかし上記の通り、これだとSuspendedのタイミングでエラる…
仕方ないので、

送る側では

string p1 = "hogehoge";
int p2 = 1234;
rootFrame.Navigate(typeof(SomePage), String.Format("{0},{1}", p1, p2));

受け取る側では

protected override async void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    string[] params = (navigationParameter as string).Split(",");
    string p1 = params[0];
    int p2 = int.Parse(params[1]);
}

としました。ただのカンマ区切りなので、もちろん、p1にカンマが入ってしまったら動かないのですけれども…


とりあえずはこれで用を足せるので、今はこの方法を使ってます。
何か、複数パラメーターを渡す良い方法があったら教えてください。


2012 9/22 23:01 追記
MSPフェローの伊勢村さんが、詳しい原因などを調べて解決策を提示してくださいました!
「文字列しか入らないならJsonにすればいいじゃない!」
という発想で、さらにJsonObjectを使いやすくしてくれるメソッド群まで用意してくださいました。
詳しくは以下のリンクをチェック。
ページ遷移パラメータをJSON文字列に変換して持ち運ぶ - Windowsストアアプリ開発

いやー、これで開発が楽になる!