第6回 データを取得して表示する連載:Windowsストア・アプリ開発入門(4/5 ページ)

» 2013年11月18日 12時22分 公開
[山本康彦(http://www.bluewatersoft.jp/),BluewaterSoft]

タイトル一覧画面を作る

 実は、まだ作っていない画面がある。現在は、メイン画面のフィード・セクションの上に付いている見出し(例えば、先ほどの画面の[@IT Insider.NETフォーラム >]という見出し)をタップすると、例外が起きてアプリが終了してしまうはずだ。ここを、RSSフィードごとのタイトル一覧画面が表示されるようにしよう。

タイトル一覧画面のスペックを決める

 ここでは、メイン画面のフィード・セクションの上にある見出しをタップして、タイトル一覧画面に遷移することにする。タイトル一覧画面には、そのRSSフィードに含まれている記事のタイトルと発行日時をタイルにして表示しよう。そして、そのタイルをタップしたら、記事表示画面へ遷移する(次の図)。

タイトル一覧画面と画面遷移(再掲) タイトル一覧画面と画面遷移(再掲)
図の右側が、これから作るタイトル一覧画面。

 タイトル一覧画面のスペックは次のようにしよう。

  • 画面のタイトルには、RSSフィードのタイトルを表示
  • 各タイルは、300px×120px、背景は青色([お気に入り]は紫)で、それぞれ記事のタイトルと発行日時を表示
  • 画面遷移は上図のとおり
  • 他への画面遷移時に、スクロール位置は記憶しない

タイトル一覧画面を実装する

○UIの実装

 プロジェクトに[基本ページ]を追加し「FeedPage.xaml」と名前を付け、XAMLコードを記述する(次のコード)。

<Page
  x:Name="pageRoot"
  x:Class="AtmarkItReader.FeedPage"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:AtmarkItReader"
  xmlns:common="using:AtmarkItReader.Common"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  xmlns:dm="using:AtmarkItReader.DataModel"
  d:DataContext="{Binding Feeds[0], Source={d:DesignData Source=/SampleData/FeedsDataSample.json, Type=dm:FeedsData}}"
  >
  <!-- 【第6回】↑元のDataContextは削除し、xmlns:dmとd:DataContextを追加 -->
  <!-- ↑ページのデータ・コンテキストにはFeedオブジェクトを設定している(後述) -->

  <Page.Resources>
    <common:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
    <!--<x:String x:Key="AppName">My Application</x:String>-->
    <!-- 【第6回】↑AppNameは削除 -->

    <!-- 【第6回】↓タイルの背景色をリソースとして定義(コードビハインドから変更可能) -->
    <SolidColorBrush x:Key="TileBackground">DodgerBlue</SolidColorBrush>
  </Page.Resources>

  <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
  <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ChildrenTransitions>
      <TransitionCollection>
        <EntranceThemeTransition/>
      </TransitionCollection>
    </Grid.ChildrenTransitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="140"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!-- Back button and page title -->
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="120"/>
        <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <AppBarButton x:Name="backButton" Icon="Back" Height="95" Margin="10,46,10,0"
        Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
        Visibility="{Binding IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Mode=Self}}"
        AutomationProperties.Name="Back"
        AutomationProperties.AutomationId="BackButton"
        AutomationProperties.ItemType="Navigation Button"/>
      <!-- 【第6回】↓{StaticResource AppName}を{Binding Title}(=フィードのタイトル)に変更 -->
      <TextBlock x:Name="pageTitle" Text="{Binding Title}"
                 Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
                 IsHitTestVisible="false" TextWrapping="NoWrap"
                 VerticalAlignment="Bottom" Margin="0,0,30,40"/>
    </Grid>

    <!-- 【第6回】↓各記事を表示するGridViewを追加 -->
    <GridView Grid.Row="1" Margin="120,0,0,40"
              Tapped="GridView_Tapped"
              ItemsSource="{Binding Items}"
              ><!-- ↑ItemsSourceにはFeedオブジェクトのItemsプロパティ
                    (=FeedItemオブジェクトのコレクション)がバインドされる -->
      <GridView.ItemTemplate>
        <DataTemplate><!-- データ・コンテキストはFeedItemオブジェクトになる -->
          <Grid Background="{StaticResource TileBackground}"
                 Width="300" Height="120" Margin="0,0,20,0">
            <Grid.RowDefinitions>
              <RowDefinition Height="*" />
              <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <!-- 記事のタイトル:FeedItemオブジェクトのTitleプロパティがバインドされる -->
            <TextBlock Text="{Binding Title}" Foreground="White" FontSize="24"
                        Margin="15,5,15,5" MaxHeight="70"
                        TextWrapping="Wrap" TextTrimming="CharacterEllipsis" />
            <!-- 記事の発行日時:FeedItemオブジェクトのPubDateプロパティがバインドされる -->
            <TextBlock Grid.Row="1" Text="{Binding PubDate}" Foreground="White" FontSize="12"
                       Margin="15,0,15,10" />
          </Grid>
        </DataTemplate>
      </GridView.ItemTemplate>
    </GridView>
  </Grid>
</Page>

タイトル一覧画面(XAML)
太字部分が、テンプレートから変更した箇所。
なお、コードビハインドにGridView_Tappedイベント・ハンドラのメソッドを実装するまでは、ビルドできない。

 ページにバインドするデータは、メイン画面とは異なる。メイン画面ではFeedsDataオブジェクトを丸ごとバインドしていた。このタイトル一覧画面では、FeedsDataオブジェクトのFeedsプロパティに含まれるFeedオブジェクトの1つをバインドする。<Page>開始タグ内に記述したデザイン時データ(d:DataContext属性)を見てほしい。「Binding Feeds[0]」として、ダミー・データに含まれるFeedオブジェクト・コレクションの最初の要素を、ページのデータ・コンテキストにバインドしている。そのほか、ページ内のコントロールに何がバインドされるかは、コード内のコメントを見てもらえば分かるだろう。

○FeedsDataクラスへの機能追加

 次にメイン画面からの画面遷移を実装したいのだが、このタイトル一覧画面に表示するデータ(=Feedオブジェクト)をどうやって取得するかが問題になる。前回で説明したように、画面遷移時のパラメータとしてFeedオブジェクトそのものは渡せない。そこで、フィードのタイトル文字列を渡して、タイトル一覧画面の方であらためてFeedオブジェクトを取得するようにしよう。

 フィードのタイトル文字列からFeedオブジェクトを取得するコードは、今後も利用することがありそうなので、タイトル一覧画面のコードビハインドではなく、FeedsDataクラスに実装しよう(次のコード)。

public sealed class FeedsData
{
  ……省略……

  public Feed GetFeed(string feedTitle)
  {
    foreach (var feed in this.Feeds)
      if (feed.Title == feedTitle)
        return feed;

    return null;
  }

  ……省略……

フィードのタイトルからFeedオブジェクトを取得するメソッドをFeedsDataクラスに追加する(C#)

○画面遷移の実装

 まず、メイン画面からタイトル一覧画面への遷移を実装しよう。メイン画面のコードビハインドには、すでにテンプレートの段階でイベント・ハンドラが置かれているので、そのメソッドの中身を書き換える(次のコード)。タイトル一覧画面へ渡すパラメータは、フィードのタイトルとする。

void Hub_SectionHeaderClick(object sender, HubSectionHeaderClickEventArgs e)
{
  HubSection section = e.Section;
  //var group = section.DataContext;
  //this.Frame.Navigate(typeof(SectionPage), ((SampleDataGroup)group).UniqueId);
  //↓【第6回】画面遷移先を修正する
  var feed = section.DataContext as DataModel.Feed;
  this.Frame.Navigate(typeof(FeedPage), feed.Title);
}

メイン画面のコードビハインド(HubPage.xaml.csファイル)にタイトル一覧画面への遷移を記述する(C#)

 メイン画面から画面遷移してきたタイトル一覧画面のコードビハインドでは、先ほど作ったGetFeedメソッドを使ってFeedオブジェクトを取得し、それをページのデータ・コンテキストにセットする(次のコード)。また、「お気に入り」フィード・セクションから画面遷移してきた場合には、ここでタイルの背景色を変える。タイルの背景色はページ・リソースにしてあるので、このようにして色を変えることができるのだ。

private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
  // 画面遷移時のパラメータとして、フィードのタイトルが渡される
  var feedTitle = e.NavigationParameter as string;

  // タイトルが合致するRSSフィードのデータを取得して、ページのデータ・コンテキストにセットする
  var feedsData = App.Current.Resources["feedsDataSource"] as DataModel.FeedsData;
  this.DataContext = feedsData.GetFeed(feedTitle);

  // [お気に入り]ではタイルの背景色を変える
  if (feedTitle == "お気に入り")
    (this.Resources["TileBackground"] as SolidColorBrush).Color = Windows.UI.Colors.BlueViolet;
}

タイトル一覧画面のコードビハインド(FeedPage.xaml.csファイル)にメイン画面からの遷移時に行う処理を記述する(C#)

 続いて、タイトル一覧画面から記事一覧画面への画面遷移を実装する。

 タイトル一覧画面に追加したGridViewコントロールには、すでに「Tapped="GridView_Tapped"」とイベント・ハンドラの記述がしてある。その中にカーソルを置き、[F12]キーを押して、コードビハインドにGridView_Tappedメソッドのスケルトンを自動生成させる。そこに記述するコードは、前回のListViewItem_Tappedメソッドとほとんど同じだ(次のコード)。

private void GridView_Tapped(object sender, TappedRoutedEventArgs e)
{
  // 第1引数は、イベントを送信してきたコントロール(=GridViewコントロール)
  var gv = sender as GridView;
  if (gv == null)
    return;

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

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

タイトル一覧画面のコードビハインド(FeedPage.xaml.csファイル)に記事表示画面へ遷移する際に行う処理を記述する(C#)

 これで、タイトル一覧画面から記事表示画面への画面遷移も完成だ。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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