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

だるろぐ

とてもだるだるした日記です http://about.daruyanagi.jp/

お知らせ

WinRT/XAML のお勉強 ―― 「分割アプリケーション」テンプレートを活かす

WinRT

f:id:daruyanagi:20120921221949p:plain

昨日、@okazuki さんにいろいろ教えてもらったのだけど、ちょっとチンプンカンプンなところもあったので、今日は「標準テンプレート縛り」で燃費管理アプリを一から開発してみた。

使ったのは 「分割アプリケーション」。2階層のデータ表示が可能なのかな。List を表示する ItemsPage.xaml と、そこで Group を選択して List を表示する SplitPage.xaml が用意されている。

f:id:daruyanagi:20120921222935j:plain

いろいろ考えてみたんだけれど、キモはこのテンプレートが要求する仕様に沿ったデータを用意することかな。

じゃぁ、仕様に沿ったデータ構造って? DataModel/SampleDataSource.cs を読むと、データは

SampleDataSource
    List: SampleDataGroup (SampleDataCommon)
        List: SampleDataItem (SampleDataCommon)

になってる。こういう感じに作ればいい。うちのアプリの場合は、

DataSource
    List: Vehicle (乗り物)
        List: RefuelLog (給油ログ)

って感じになるかな。乗り物=Group、給油ログ=Itemというイメージ。

んで、Group も Item も SampleDataCommon を継承している。要は UniqueId、Title、Subtitle、Description、Image というプロパティを持ちなさいということだ。実装したら、テンプレートでバインドされますよ、と*1

でも、だったらインターフェイスでもいいわけで、

namespace App5.Common
{
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Imaging;

    public interface ITemplateGridViewItem
    {
        Guid UniqueId { get; } // <- string は嫌だったので改造
        string Title { get; }
        string Subtitle { get; }
        string Description { get; }
        ImageSource Image { get; }
        ITemplateGridViewItem Parent { get; } // <- なくてもいい
    }
}

というのを作って、Group/Item はこれを実装するということにした。乗り物データと給油ログデータが一つのデータから継承されてるってなんかアレだけど、インターフェイスなら個人的にしっくりくる。

燃費管理アプリのデータには、タイトルやサブタイトルなどという概念はない。でも、そこは給油量(Amout)や日付(Date)といったふさわしいプロパティを別途もっておいて、

public string Title
{
    get { return string.Format("{0:#,##0.00 L}", amount); }
}

public string Subtitle
{ 
    get { return date.ToString("d"); }
}

という感じで、ビューに表示したいデータ(給油量をタイトルに、日付をサブタイトルに)を適当に返せばいい。なんか M-VM を分けたくなってきたね。まぁ、それは今度でいい。今回はこの汚い実装のまま先に進もう。DataSource(自分で書いたデータソース)も、SampleDataSource のコピペをベースにあまり構造を変えないように実装していく。

あとは SampleDataSource.cs を消すなりリネームして、ビルドエラーが出た個所をこちょこちょ DataSource に置き換えれば、こんな感じ!

f:id:daruyanagi:20120921225136p:plainf:id:daruyanagi:20120921225137p:plainf:id:daruyanagi:20120921225140p:plainf:id:daruyanagi:20120921225143p:plain

さすが標準テンプレート、Snapped にもばっちり対応だぜ。

デザイン時バインディング

Page.Resource の CollectionViewSource で、d:Source って書いてある部分は、デザイン時のみ有効なデータバインディング。これをやっておけばサンプルデータがバインディングされて、デザインがやりやすくなる。

<Page.Resources>

    <!-- このページで表示されるアイテムのコレクション -->
    <CollectionViewSource
        x:Name="itemsViewSource"
        Source="{Binding Items}"
        d:Source="{Binding AllGroups[0].Items, Source={d:DesignInstance Type=local:DataSource, IsDesignTimeCreatable=True}}"/>
</Page.Resources>

標準では DataModel/SampleDataSource がバインディングされているけれど、これもちょちょいと local:DataSource *2に書き換えれば……

f:id:daruyanagi:20120921222338p:plainf:id:daruyanagi:20120921222344p:plain

うおおー、デザイン時にもバインディングされてる。これは超便利だな!

ちょっとわかった気がするので、これでテンプレートから足を踏み外せるぜー。これで今日のお勉強は終わり!

*1:SplitPage ではこれに加えて Content というプロパティも要求する

*2:local はアプリケーションの名前空間。XAML の最初のほうに定義してある