連載
» 2013年12月13日 16時17分 公開

連載:Windowsストア・アプリ開発入門:第8回 入力されたデータを保存する (2/6)

[山本康彦(http://www.bluewatersoft.jp/),BluewaterSoft]

「お気に入り」機能を作る

スペックを考える

 今回は、「お気に入り」に追加する機能だけを実装しよう。追加するのも、記事表示画面だけからとする。

 エンドユーザーの操作としては、記事表示画面でアプリバーを出し、[お気に入りにする]ボタンをタップしてフライアウト(=ポップアップ)を出し、必要ならコメントを入力してから[追加]ボタンをタップするものとしよう(次の画像)。

「お気に入り」に追加するためのUI 「お気に入り」に追加するためのUI
アプリバーの左端のボタンで「お気に入りに追加する」フライアウトを出したところ。

 その他、「お気に入り」に求められるスペックは次のようなものだ。

  • 「お気に入り」に入れると、メイン画面と「お気に入り」一覧画面に反映される
  • 「お気に入り」は、「お気に入り」に入れた日時が新しいものから順に並べる
  • 同じ記事を「お気に入り」に入れると、以前の「お気に入り」は消える
  • 一定数を超える「お気に入り」を入れると、最も古いものが消える
  • アプリ終了後、再びアクティベートすると、メイン画面と「お気に入り」一覧画面の「お気に入り」が復元される
  • 「お気に入り」はローミングされる。ローミングされた側は、そのときに(または次に動作したときに)データを画面に反映させる

 なお、「お気に入り」を削除/編集する機能や、メイン画面と一覧画面でも「お気に入り」にアクセスする機能も欲しくなるだろうが、本稿では扱わない(別途公開しているサンプルコードには削除機能も実装してあるので参考にしてほしい)。

「お気に入り」に追加する機能を実装する

 「お気に入り」に追加する機能を実装するには、保持するデータの改修が必要になる。その上で、ロジックとUIを作り、最後にそれらを組み合わる。

データクラスを改修する

 「お気に入り」として保持するデータには、1件の記事を表すFeedItemクラスのオブジェクトを使えばよさそうだ。ただし、スペックのところで述べたように、エンドユーザーが入力したコメントも保持したい。今回は、FeedItemクラスを改修して、コメントも保持できるようにしよう(次のコード)。

[System.Runtime.Serialization.DataContract]
public class FeedItem
{
  ……省略……

  [System.Runtime.Serialization.DataMember]
  public string FavoriteComment { get; set; }
}

FeedItemクラスにコメントを保持するためのプロパティを追加する(C#)
プロジェクトのDataModelフォルダーにある「FeedsData.cs」ファイルに、太字の部分を追加する。

 これで、ダウンロードしたRSSフィードのデータと同様に「お気に入り」のデータも扱えるようになった。「お気に入り」のデータの1件はFeedItemオブジェクトとして、「お気に入り」のデータの全体はFeedオブジェクトとして表現できる。

「お気に入り」をファイルに読み書きするロジック

 「お気に入り」のデータ(=Feedオブジェクト)を、アプリケーションデータ記憶域のファイルに書き出し、また読み込む機能が必要だ。そのような「お気に入り」のデータを管理するクラスを作る。プロジェクトのLogicフォルダーに新しいクラスを追加し、ファイル名を「FavoriteStorage.cs」とする。

 FavoriteStorageクラスではWinRTのストリームと.NET Frameworkのストリームを変換することになる。変換のための拡張メソッドがWindowsRuntimeStreamExtensionsクラス(System.IO名前空間)にあるので、それを使えるようにusingの宣言を追加しておく(次のコード)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AtmarkItReader.DataModel;

using System.IO;  // WindowsRuntimeStreamExtensionsを利用する

namespace AtmarkItReader.Logic
{
  // 【第8回】「お気に入り」のデータを管理するクラス
  public class FavoriteStorage
  {
    ……省略……

FavoriteStorageクラスではWindowsRuntimeStreamExtensionsの拡張メソッドを利用する(C#)
太字の部分を追加する。

 「お気に入り」のデータを保存しておくファイルの名前は「Favorite.xml」としよう。保存するフォルダーは、アプリケーションデータ記憶域のローミングフォルダーとする。そして、保存するフォルダーのストレージオブジェクトをDataFolderというプロパティで参照できるようにしておこう(次のコード)。

public class FavoriteStorage
{
  private const string FileName = "Favorite.xml";

  private static Windows.Storage.StorageFolder DataFolder
  {
    get { return Windows.Storage.ApplicationData.Current.RoamingFolder; }
  }
}

保存するファイルとフォルダーをFavoriteStorageクラスに定義する(C#)

 フォルダーを表すストレージオブジェクトのTryGetItemAsyncメソッドを使うと、フォルダー内のファイルやフォルダーを取得できる。次のコードのようにして、「Favorite.xml」ファイルのストレージオブジェクトを取得する。

public class FavoriteStorage
{
  ……省略……

  internal static async Task<Windows.Storage.StorageFile> GetDataFileAsync()
  {
    return (await DataFolder.TryGetItemAsync(FileName)) as Windows.Storage.StorageFile;
  }
}

「Favorite.xml」ファイルのストレージオブジェクトを取得する(C#)
引数に渡された名前のファイルやフォルダーが存在しないとき、TryGetItemAsyncメソッドはnullを返す(例外は出ない)。そのため、このメソッドは、「Favorite.xml」ファイルが存在しないときはnullを返し、存在すればStorageFileオブジェクトを返す。

 「お気に入り」のデータをファイルから読み出してみよう。上のコードを使ってStorageFileオブジェクトが得られたら、そのOpenAsyncメソッドを呼び出すとWinRTのストリームが得られる。WindowsRuntimeStreamExtensionsクラスのAsStream拡張メソッドを使って、それを.NET Frameworkのストリームに変換する。今回は、XmlSerializerクラス(System.Xml.Serialization名前空間)を使って、そのストリームからFeedItemオブジェクトの配列にデシリアライズさせる(次のコード)。

public class FavoriteStorage
{
  ……省略……

  internal static async Task<FeedItem[]> LoadAsync()
  {
    var file = await GetDataFileAsync(); // 「Favorite.xml」ファイルのストレージオブジェクトを取得
    if (file == null)
      return null;

    try
    {
      using (var ras = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) // 読み込み専用としてストリームを開く
      using (var stream = ras.AsStream()) // .NET Frameworkのストリームに変換
      {
        // ストリームからFeedItemオブジェクトの配列にデシリアライズ
        var serializer = new System.Xml.Serialization.XmlSerializer(typeof(FeedItem[]));
        var feedItems = serializer.Deserialize(stream) as FeedItem[];
        return feedItems;
      }
    }
    catch
    {
      return null; // ファイルの読み込みやデシリアライズに失敗したときはnullを返す
    }
  }
}

「Favorite.xml」ファイルを読み出してFeedItemオブジェクトの配列にデシリアライズする(C#)
FeedItemクラスを利用するため、「using AtmarkItReader.DataModel;」を追加する必要がある。

 次に、データの書き込みだ。ファイルに書き込むときには、ファイルが存在しなければ新たに作成する。すでにファイルが存在していたら、上書きする。フォルダーを表すストレージオブジェクトのCreateFileAsyncメソッドを使うと、そのような使い分けが引数で指定できる。CreateFileAsyncメソッドでStorageFileオブジェクトが得られたら、読み込みと同様な手順を踏んで.NET Frameworkのストリームを取得し、XmlSerializerクラスにシリアライズさせる(次のコード)。

public class FavoriteStorage
{
  ……省略……

  private static async Task SaveAsync(FeedItem[] items)
  {
    try
    {
      var file = await DataFolder.CreateFileAsync(
                          FileName,
                          Windows.Storage.CreationCollisionOption.ReplaceExisting
                          // ↑ファイルがあれば上書き、無ければファイルを作成
                        );
      using (var ras = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite)) // 読み書き用としてストリームを開く
      using (var stream = ras.AsStream()) // .NET Frameworkのストリームに変換
      {
        // FeedItemオブジェクトの配列をシリアライズしてストリームに書き出す
        var serializer = new System.Xml.Serialization.XmlSerializer(typeof(FeedItem[]));
        serializer.Serialize(stream, items);
      }
    }
    catch { }
  }
}

FeedItemオブジェクトの配列をシリアライズして「Favorite.xml」ファイルに書き出す(C#)

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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