CakePHPのXMLレスポンスをストアアプリで一覧表示する

CakePHPのXMLレスポンスをWPFで一覧表示する | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5370

の Windows ストアアプリ版も作ってみます。

本当はListViewを使いたいところだけど、手始めに GridView を使うところから。もっと、WPFのListViewのようなダサいデザインを手軽に作れればいいのですが。どうもうまくいかない。

■データモデルを作る

WPFで作ったソースをそのまま流用しますが、一か所だけ違います。リフレクションでプロパティを取ってくるところで、拡張メソッドの GetTypeInfo を使います。なんで、こんな風にしたのか不明なのですが。

[code lang=”csharp”]
using System.Reflection;

public class IModel
{
public void FormXml(XElement el)
{
// WinRTの場合
var pis = this.GetType().GetTypeInfo().DeclaredProperties;
foreach (var pi in pis)
{
var vv = el.Descendants(pi.Name).FirstOrDefault();
if (vv != null)
{
var v = vv.Value;
if (pi.PropertyType == typeof(int))
pi.SetValue(this, int.Parse(v));
else if (pi.PropertyType == typeof(double))
pi.SetValue(this, double.Parse(v));
else if (pi.PropertyType == typeof(string))
pi.SetValue(this, v);
}
}
}
}
[/code]

POJO なクラスはそのままで。

■グリッドビューを作る

VS2013 でグリッドのテンプレートを作ると、きれいな GridView のテンプレートを吐き出してくれるけどカスタムしにくいので、最小限のコードだけにします。

[code lang=”xml”]


[/code]

データのバインドは「ItemsSource=”{Binding Items}”」なところで。このあたりは WPF と同じ。GirdView に表示するアイテムのテンプレートは、「ItemTemplate=”{StaticResource StoreTemplate}”」で指定してます。既存のデータテンプレートを使うと、バインド名が Title や Subtitle に固定になっているので、ここはカスタムで。StaticResource せずとも、GridView.ItemTemplate を使って以下のようにも書けます。

[code lang=”xml”]










[/code]

1回だけしか使わない場合はこれで十分ですよね。そもそも、StaticResource って、その xaml 内に限るからあまりそこに書く理由はあまり意味ないかも、と思ってたり。

ページリソースに記述する場合はこんな感じで「StoreTemplate」のように名前を付けておきます。デザイン用のデータを読み込んでちまちま修正するパターンもできるので、これはこれで便利だし。他のプロジェクトからコピペする場合も便利。

[code lang=”xml”]








[/code]

デザイン用のデータは、VS2013 から JSON 型式で読み込めるようになったのですが、何故か日本語が通りません。UTF-8 にしてもダメなので、なんか XAML デザイナのほうで変なことをやっている気がします。英語(ASCII文字)だけにすると通ります。

■プロパティビューっぽいもの

VS2013が作ってくれるデザインテンプレートでは、アイテムをクリックすると詳細画面に遷移しますが、ここは WPF と同じように同一の画面に表示させます。いちいち画面遷移するのも面倒だし(特に戻るのが面倒)、でかい画面を切り替えるよりも、画面を自前で分割するほうがいいよってことで。

[code lang=”xml”]




[/code]

バインドは、Item の下にプロパティをつける形にしておきます。この構造は、先のデータモデルと合わせておきます。当然名前も一緒にしないとダメ。

■バインド用のモデルを作る

ここは WPF と同じ。

[code lang=”csharp”]
public class BindModel : BindableBase
{
private ObservableCollection _Items;
public ObservableCollection Items
{
get { return _Items; }
set { this.SetProperty(ref this._Items, value); }
}

private Model.Store _Item;
public Model.Store Item
{
get { return _Item; }
set { this.SetProperty(ref this._Item, value); }
}
}
[/code]

■DataContextに設定する

DataContext に設定する方法も同じ。ストアアプリでは、DefaultViewModel がある訳ですが、実質同じことをやるので、どちらかを使えば OK です。

[win8] DefaultViewModel と DataContext は同時に使えない | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3873

に書いた通り「バインディングするところがアレ」なので、DataContext で十分かなと思ったりします。コードレベルで WPF との共有も考えると、業務コード的にはどっちかに統一しておいたほうがよいかも。覚えることが少なくなるし。

[code lang=”csharp”]
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
// モデルをバインドする
_model = new BindModel();
this.DataContext = _model;
}

private BindModel _model;

///

/// 一覧を取得
///

/// /// private async void Button_Click(object sender, RoutedEventArgs e)
{
var lst = await new Api.ApiStore().Read();
_model.Items = new ObservableCollection(lst);
}
///

/// アイテムをクリックしたとき
///

/// /// private void itemGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = e.AddedItems[0] as Model.Store;
_model.Item = item;
}
}
[/code]

これで API 呼び出しをして、GridView のアイテムをちまちまとクリック(タブレットの場合はタップ)すると、詳細情報が右のプロパティ一覧に表示されます。

ちなみに、WPFでテキストボックスにバインドをすると初期値が TwoWay(双方向)になっていますが、ストアアプリの場合は OneWay(表示のみ)です。あとストアアプリの場合、それぞれのプロパティに INotifyPropertyChanged をつけないと、TwoWay にならないのが面倒かなと。このあたり VS2012 のグリッドのサンプルにはあったのだけど、VS2013 のグリッドのサンプルにはないんですよね。

GridView の場合は横スクロールなので、お次は ListView を使って縦スクロール(WPFのリスト表示と同じパターン)で作ってみます。

カテゴリー: CakePHP, WPF, WinRT パーマリンク