連載
» 2013年11月01日 15時41分 公開

連載:Windowsストア・アプリ開発入門:第5回 データを画面に表示する (5/5)

[山本康彦(http://www.bluewatersoft.jp/),BluewaterSoft]
前のページへ 1|2|3|4|5       

2つ目の画面への遷移時にデータを渡す

 さて、以上のメイン画面の変更により前回で実装した画面遷移が動かなくなっている。画面遷移を実装し直すとともに、今回はデータも渡すようにしてみよう。

2つ目の画面への遷移を再び実装する

 「残りのセクションのデータ・バインド」で作り直したListViewコントロール(全部で3箇所ある)の開始タグに、イベント・ハンドラを追加する(次のコード)。

<ListView Width="500"
          Tapped="ListViewItem_Tapped"
          ItemsSource="{Binding Items}"
          >

メイン画面のフィードのリストにTappedイベント・ハンドラを追加した(XAML)
「ListViewItem_Tapped」というイベント・ハンドラは、前回作ったものだ。前回は個々のListViewItemコントロールに付けたので、このような名前にしたのだ。ここではListViewコントロールに付けているので不適切な名前になっているが、そのままにしておく。気になるようなら、次のメソッドとともに「ListView_Tapped」に直してほしい。

 コードビハインドには、このイベント・ハンドラを処理するメソッドがすでにある(次のコード)。これは前回作成したものだ。

private void ListViewItem_Tapped(object sender, TappedRoutedEventArgs e)
{
  //画面遷移(引数無し)
  this.Frame.Navigate(typeof(ViewPage));
}

前回作成したイベント・ハンドラ(C#)

 2つ目の画面への遷移が、これで再び動作するようになった。

画面遷移時にデータを渡すには?

 Navigateメソッドの第2引数を使う。ただし、渡せるデータは文字列や数値などの基本型のみだ*11

 ユーザーがタップした項目に結び付けられているFeedItemオブジェクトをそのまま渡せればよいのだが、基本型しか渡せないので何か工夫が必要だ。主な選択肢は、次の2つ。

  • ユニークなID: データ全体で一意になるようなIDをFeedItemオブジェクトごとに与えておき、そのIDを渡す
  • 文字列を結合する: 遷移した先の画面で必要になるデータを全部文字列にして、タブ文字などで1つの文字列に結合してから渡す

 FeedItemオブジェクトが持つ情報は少ない(文字列のプロパティが3つだけ)ので、ここでは2番目の方法を使おう。次のコードのように、FeedItemオブジェクトの3つのプロパティ値をタブ文字で結合して、Navigateメソッドの第2引数として渡す。

private void ListViewItem_Tapped(object sender, TappedRoutedEventArgs e)
{
  // 画面遷移(引数を渡すように変更)

  // 第1引数は、イベントを送信してきたコントロール(=ListViewコントロール)
  var lv = sender as ListView;
  if (lv == null)
    return;

  // ListViewコントロールのSelectedItemプロパティには、データ・バインドされたFeedItemオブジェクトが入っている
  var item = lv.SelectedItem as AtmarkItReader.DataModel.FeedItem;
  if (item == null)
    return;

  // FeedItemオブジェクトのプロパティの値をタブ文字を区切りとして結合し、それを引数として画面遷移する
  var param = string.Join("¥t", item.Title, item.Link, item.PubDate);
  this.Frame.Navigate(typeof(ViewPage), param);
}

データを渡すように変更したイベント・ハンドラ(C#)

*11 Navigateメソッドの定義上は、どんなオブジェクトでも渡せる。基本型のみという制限は、プロジェクト・テンプレートに含まれているSuspensionManagerクラス(Commonフォルダ内の「SuspensionManage.cs」ファイル)によるものだ。アプリの中断時/再起動時にSuspensionManagerクラスがアプリの状態を保存/復元するのだが、そのときにシリアライズ/デシリアライズできる型でないといけないのだ。


 さて、2つ目の画面の方は、渡されたデータを受け取るように変更する。受け取った文字列からFeedItemオブジェクトを生成して、画面のデータ・コンテキストにセットしてみよう(次のコード)。

private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
  // 画面遷移するときに、引数としてTitle/Link/PubDateを渡してもらう
  var param = e.NavigationParameter as string;
  if (param == null)
    return;

  // 引数の文字列をバラして、FeedItemオブジェクトを作り直す
  var paramArray = param.Split('¥t');
  var item = new AtmarkItReader.DataModel.FeedItem(
                                            title: paramArray[0],
                                            link: paramArray[1],
                                            pubDate: paramArray[2]
                                          );

  // FeedItemオブジェクトをデータ・コンテキストにセット
  this.DataContext = item;
}

「ViewPage.xaml.cs」ファイルを変更してデータを受け取るようにした(C#)
今回のプロジェクトのようにNavigationHelperクラスを利用している場合は、このようにしてnavigationHelper_LoadStateメソッドでデータを受け取る。NavigationHelperクラスを使っていない場合は、OnNavigatedToメソッドで受け取る(そのときは引数のNavigationEventArgsオブジェクトのParemeterプロパティにデータが入ってくる)。

2つ目の画面でもデータ・バインドを行うようにする

 以上の変更で、2つ目の画面が表示されるときには、画面のデータ・コンテキストにFeedItemオブジェクトが入っているようになった。あとはデータ・バインドを使って画面に表示できる(次のコード)。

  <!--<TextBlock x:Name="pageTitle" Text="{StaticResource AppName}"
             Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" IsHitTestVisible="false"
             TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>-->
  <!-- ↓バインディングに変更 -->
  <TextBlock x:Name="pageTitle" Text="{Binding Title}"
             Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" IsHitTestVisible="false"
             TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>

  ……省略……

<!--<WebView x:Name="webView1" Grid.Row="1"
         Source="http://rss.rssad.jp/rss/artclk/2CqtlBidiijV/……省略……qL0QyMbww9"
         />-->
<!-- ↓バインディングに変更 -->
<WebView x:Name="webView1" Grid.Row="1"
         Source="{Binding Link}"
         />

「ViewPage.xaml」ファイルの変更部分(XAML)
前回、ハード・コーディングした部分(pageTitleのText属性とwebView1のSource属性)をデータ・バインドに変更した。

 以上で今回の実装は完了だ。デザイン時に2つ目の画面のタイトルが表示されないが、必要ならばデザイン時データを画面に追加してほしい*12

*12 これは読者のみなさんへの宿題としよう。ヒントとしては、「『データ・バインド』による方法」でやったようにしてTextBlockコントロールに「d:DataContext="仮のタイトル"」などとしてもダメだということ。なぜなら、今度は「{Binding Title}」としていて、データ・コンテキストの中の「Title」という名前のオブジェクトにバインドしているからだ。デザイン時データは、単純な文字列ではなく、「Title」という名前のオブジェクトを持ったオブジェクトにしないといけない(FeedItemオブジェクトにすれば後からも分かりやすいだろう)。別途公開するサンプル・コードには例を載せておく。


まとめ

 今回は、データ・バインドの基礎を学び、これまでに作った画面をデータ・バインドに変更した。そして、ダミーのデータを、デザイン時と実行時に表示させる方法も学んだ。また、画面遷移のときにデータを受け渡す実装をした。

  • データ・バインドでは、コードビハインドからデータ・コンテキストにデータをセットし、画面ではデータ・コンテキストからデータを取り出して表示する
  • 画面に表示するデータは、クラスを定義して1つにまとめる(そうしないとデータ・バインドが煩雑になる)
  • デザイン時にダミー・データを簡単に表示できる。データはJSONかXAMLで用意する
  • 実行時にダミー・データを表示するには自前の実装が必要だ。そのような表示が必要なときに限って実装すればよい
  • 画面遷移時にデータを渡すには文字列などの基本型を使う

 次回は「データを取得して表示する」。WebサービスからRSSフィードを実際に取得して、画面に表示させてみる予定だ。いよいよアプリが形になってくる。

「連載:Windowsストア・アプリ開発入門」のインデックス

連載:Windowsストア・アプリ開発入門

前のページへ 1|2|3|4|5       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。