少し時間があきましたが、今回はグリッドアプリケーションを使った場合にどのようにカスタマイズするかということを説明します。最初に、開発体験テンプレートをご存じな方も多いことと思います。このテンプレート集のNewReaderのReadme.txtにカスタマイズのポイントが記載されているので、その中から抜粋したものを以下に示します。
最初にブランディングを説明します。ブランディングに関係する事項として、以下のようなことを考慮する必要があります。
特にブランディングは重要で、作成したアプリが容易に識別できるようにするためにも必須となります。また、アプリ内の各種のページ設計などを含めて統一感を持ってデザインすることが重要となり、これらの統一がアプリの印象を利用者に認識してもらうのに役立ちます。 このブランディングを考える上で、最初に取り組むのが背景色の変更だと思います。Windows ストア アプリのテンプレートでは、テーマという機能が含まれておりデフォルトのテーマは「Dark」となっています。これをSDKサンプルのように白を基調としたテーマにするには、App.xamlに「RequestedTheme」属性を記述します。
<Application ・・・・・ RequestedTheme = "Light" ・・・・・ >
アプリの名前を変更するのも忘れないようにしましょう。アプリの名前は、App.xamlに「AppName」というキーを持つリソースとして定義されています。
プライバシーポリシーは、ネットワーク通信を行うアプリでは必須となります。Windows 8 アプリの認定の要件 (Windows)の要件4.1.1に「ユーザーの IP アドレスなどの個人情報をアプリで収集または送信する場合は、」とあり、収集するかしないは別として通信を行う場合は通信インフラストラクチャーがIPアドレスを送信します。この理由から、プライバシーポリシーを用意することが必須となります。特に、Visual Studioで作成した新規プロジェクトではデフォルトで「インターネット」が有効になっているので、注意しましょう。用意するプライバシーポリシーは、以下の2ヶ所への明示が必須となります。
Package.appmanifestは、特に以下の点を正しく設定します。
パッケージ名やパッケージ表示名は、意図的にデフォルトの値にしておくこともあります。これは、セキュリティ上の理由です。Windows ストアアプリは、インストール自体がパッケージ名単位で行われます。逆を言えば、パッケージ名が理解しやすいと、カジュアルハックがし易いとも言えます。カジュアルハックと言っても、パッケージのローカルストア(ユーザー プロファイルの中にあります)をWindows エクスプローラーなどで覗いたりという意味です。パッケージ名を変更することは、一見しただけでアプリとの関連付けを連想させないためだけに、アプリと関係の無いパッケージ名やパッケージ表示名にしておくという程度の効果しかありません。この理由は、タスクマネージャーなどを使うことで、パッケージ名を利用者が知ることができるからです。
ここまで説明してきたのは、NewReaderテンプレートのReadme.txtに基づいています。新規のグリッドアプリケーションを自分で作成した場合は、データソースの変更が最初に行うステップとなります。以下に記載するのは、必ずではありませんが、このような考え方でNewsReaderはデータソースをカスタマイズしたと理解して頂ければ結構です。
簡単に言えば、自分が作成するアプリが必要とするデータに応じてデータモデルを変更するということです。また、ズームアウトビューに対応させるために、必要なプロパティの実装を行ったり、オフラインサポートに応じて必要な機能を実装したりする必要があるということです。もちろん、オフラインサポートが必須というわけではありません。が、アプリを使用するユーザーにとってモバイルシーンでは必須とも言えるでしょう。
データソースを変更すれば、そのデータの表示方法も変更させる必要があります。具体的には、データテンプレートを自分のデータ用にカスタマイズする作業となります。この目的で、NewsReaderテンプレートは以下のようにApp.xamlでデータテンプレートを定義しています。
NewsReaderテンプレートでは、アプリバーなどを導入しており、そのために必要となるスタイルをApp.xamlにリソースとして定義しています。これ以外に、行うカスタマイズとしては、次に説明するようなものがあります。
Visual Sudioではテンプレートの用意がありませんので、NewsReaderテンプレートなどのApp.xaml.csから必要なコードを引用してください。特に、プライバシーポリシーの明示を行うには必須となる作業です。
Visual Studioを使ってプロジェクトへ[追加]-[新しい項目]で表示されるウィザードを使って、検索コントラクト、あるいは共有ターゲットコントラクトを追加して雛形を作成します。追加した後に、以下の作業を行います。
15秒以内にアクティブ化を完了する
Windows ストアアプリでは、タイルをタップしてから起動が完了するまでに15秒を超えるとシステムがアプリを強制終了する仕組みを備えています。たとえばNewsReaderテンプレートなどは、BlogやTwitterをネットワークを使って読み込んでデータソースを作成しますから、容易に15秒という時間を超えてしまいます。仮に、15秒を超えていればシステムに強制終了させられるため、アプリが起動することはなくなってしまいます。この症状を避けるためにNewsReaderテンプレートが行っている方法は、以下のようなものです。
この対策を行っても複数のフィードを行うとビューが表示されるまでに、時間がかかることになってしまいます。この理由から、NewsReaderテンプレートでは、1)1画面に収まるデータの取得、2)残りのデータを取得の2段階に分類しており、後者を非同期に処理しています。つまり、ビューが表示された後も、データの読み込みを続けるので徐々にデータが増えていくという動作を行うことで、ユーザーがビューを操作できるようになる時間の短縮を行っています。 このような手法には、画一的なアプローチはなく、取り扱うアプリのコンセプトやデータによって最適と思われる方法を使っていく必要があります。そのためには、作成されたアプリのボトルネックが何処に存在するかを調査して、その結果をもとに解決策を考えていきます。ちなみに要件3.8では、「5秒以内に起動すること」とあり、起動時にかけられる制限は厳しくなっています。つまり、データの初期化を同期的に行うのではなく、非同期処理を適切に組み合わせる必要があるということになります。
5秒以内に一時停止を完了する
Windows ストアアプリでは、アプリがバックグラウンドに移行するとシステム側がシステムリソースとの関係で一時停止させたり、強制終了させたりする場合があります。この時の状態遷移は、「一時停止」-[復帰]、[一時停止]-[強制終了]の2種類となります。一時停止に伴い、Suspendイベントがアプリに通知されるため、Suspendイベントの処理は「5秒以内に完了」する必要があります。仮に、5秒を超えるとシステムがアプリを強制終了させます。 一般的に一時停止イベントで行う処理は、以下のようなものです。
この動作は、強制終了された後にアプリを起動した時に、強制終了させられた状態にアプリを復帰させる場合は実装する必要があります。既に説明したようにグリッドアプリケーションは、SuspensionManagerによってFramのナビゲーション履歴を保存するようになっています。従って、この機能を有効にしている限りは、セッションデータの保存と復帰は必須となります。問題は、セッションデータの保存と復帰の実装コードを何処に記述するかという点になります。
NewsReaderテンプレートでは、RSSなどのフィードの読み込みが完了した時にデータを保存するようにしています。この手法の根底にある考え方は、データモデルに変化があったタイミングで保存するというものです。この当たりの考え方も統一的なものはありませんので、作成されるアプリに応じて考えるものとなります。ちなみに要件3.8では、「2秒以内に中断を実行できること」とあり、かなり厳しくなっています。要件3.8が厳しくなっている理由は、非力なPCのサポートを前提に置いていると考えると良いでしょう。つまり、サポートCPUを限定すれば問題がなくなることも少なくないということになります。
ユーザーコントロールを作成するには
C#やVB、そしてC++でxamlを使って開発される場合は、ユーザーコントロールを作成したい場合もあることでしょう。ユーザーコントロールを作成する場合に、注意するのはデータバインドとVisualStateManagerによるビューをどのように切り替えるかという点になります。最初に、簡単なXAMLの定義を以下に示します。
<UserControl x:Class="App4.MyUserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App4" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="self" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid> <TextBox x:Name="txtInput" Width="{Binding Width, ElementName=self}" Height="{Binding Height, ElementName=self}" Text="{Binding Data, ElementName=self, Mode=TwoWay}" /> </Grid> </UserControl>
ユーザーコントロールにTextBoxを置いただけのシンプルなxamlです。このxaml定義で、注意する必要があるのはUserControlのName属性とデータバインドの記述方法の2種類になります。
次にユーザーコントロールに実装したコードを以下に示します。
// 依存プロパティの定義 public static DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(string), typeof(MyUserControl1), new PropertyMetadata(string.Empty, new PropertyChangedCallback(MyUserControl1.OnDataChanged))); // プロパティ変更のイベントハンドラー private static void OnDataChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { var myUserControl1 = (MyUserControl1)obj; myUserControl1.Data = (string)args.NewValue; } // 依存プロパティの実装 public string Data { get { return this.GetValue(DataProperty) as string; } set { this.SetValue(DataProperty, value); } }
コードを見れば理解できると思いますが、DependencyPropertyを定義する必要があります。この定義で注意すべきことは、PropertyMetadataの定義だと思います。双方向バインディングを行う場合は、PropertyMetadataの第2引数にPropertyChangedCallbackを指定します。一方向バインディングであれば、第2引数はnullで構いません。この点が、データバインド可能なプロパティを実装する上での注意点となります。次に、このコントロールを使用するXAMLの定義を以下に示します。
<local:MyUserControl1 x:Name="myControl1" Data="{Binding Data, Mode=TwoWay}" Margin="95,127,0,0" Width="430" Height="65"/>
後は、myControl1のDataContextにデータソースを設定することで、データバインドは完了となります。 上記で説明したことは、データバインド可能なユーザーコントロールを作成する上での最低限の知識となります。次に、VisualStateManagerを定義する上で注意する点を以下に示します。
上記に説明したのは、基本的な方法となります。もちろん、LayoutAwarePageを使用しない場合ではビューの切り替えを自分で考える必要があります。たとえば、ウィンドウのSize変更イベントなどを使って、ユーザーコントロール内で適切なビューに合わせて配置を変更するなどの方法も考えられます。この方法の欠点は、デザイン時のビューの確認をどうするかということです。デザイン時に確認したいとなれば、XAML内にVisualStateManagerを定義せざるを得ません。