xamarin.formsでのmvvm利用のコツ
DESCRIPTION
Xamarin.Forms の MVVM パターンの解説です。 MVVM の基礎と、Xmarin.Forms 特有の MVVM パターンを説明しています。TRANSCRIPT
Xamarin.Forms でのMVVM 利用のコツ
Microsoft MVP C#
増田 智明Moonmile Solutions
自己紹介
増田 智明 [email protected]
執筆業&プログラマ C# による iOS, Android, Windows アプリケーション開発入門 逆引き大全 Visual C# 2013, Visual Basic 2013
逆引き大全 iPhone/iPad アプリ開発 作って覚える iPhone/iPad アプリ入門
アジェンダ
シンプルに MVVM の仕組みを知るMVVM の得意なところを知るXamarin.Forms 特有の MVVMMVVM の限界を知る
シンプルに MVVM の仕組みを理解必要な時にを必要なものだけを使う
シンプルな MVVM
View ViewModel Model
XAML DataGlue
ViewModel(Model)XAML
ViewModel にデータを含ませてしまうことが多い
シンプルに実装したいから
クラス分けする
View ViewModel Model
XAML ViewModelClass
Codebehind
*.cs
INotifyPropertyChangedICommand
Azure/Web API
etc
Binding の関係( Label )
XAML ViewModel+ModelClass
Codebehind
*.cs
<ContentPage> <Label Text="{Binding Name}"/>
public class MyItem : BindableBase { private string _Name; public string Name { get { return _Name; } set { this.SetProperty(ref this._Name, value); } }
var vm = new MyItem();this.BindingContext = vm;
Binding の関係( Label )
XAML ViewModel+ModelClass
Codebehind
*.cs
<ContentPage> <Label Text="{Binding Name}"/>
public class MyItem : BindableBase { private string _Name; public string Name { get { return _Name; } set { this.SetProperty(ref this._Name, value); } }
var vm = new MyItem();this.BindingContext = vm;
Binding の関係( ListView )
XAMLViewModel+Model
ClassCodebehin
d*.cs
<ListView> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Label Text="{Binding Name}" />
public class MyItems : ObservableCollection<MyItem> {
var items = new MyItems();lv.ItemsSource = items;
public class MyItem : BindableBase { private string _Name; public string Name { get; set; } { get { return _Name; } set { this.SetProperty(ref this._Name, value); } }※ ただし、一度だけの表示であれば、
INotifyPropertyChanged を実装する必要はない。
Binding の関係( ListView 複合)
XAML
ViewModel+ModelClassCodebehin
d*.cs
<ContentPage> <ListView ItemsSource="{Binding Items}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Label Text="{Binding Name}" />
public class MyItems : ObservableCollection<MyItem>{
var vm = new MyViewModel();this.BindingContext = vm;
public class MyItem : BindableBase{ private string _Name; public string Name { get; set; } { get { return _Name; } set { this.SetProperty(ref this._Name, value); } }
public class MyViewModel{ public MyItems Items { get; set; }
シーケンス図( ViewMode で変更)
XAML ViewModelCodebehin
d*.cs
Binding
INotifyPropertyChanged
Change
Display
Create
シーケンス図( View で変更)
XAML ViewModelCodebehin
d*.cs
Binding
Changed
Lookup
Changed
Create
Entry の入力を Label に反映するパターン
XAML ViewModelCodebehin
d*.cs
Changed
Changed
INotifyPropertyChanged
Change
Display
ユーザの入力を自動で View に反映させ
るトリック
ICommand の関係
XAML
ViewModel+ModelClass
Codebehind
*.cs
<ContentPage> <Button Command="{Binding UpdateCommand}"/>
var vm = new MyItem();this.BindingContext = vm;
this.UpdateCommand = new Command(() => { });
Xamarin.Forms.Command で Icommand を実装できる
ICommand の関係(パラメータ付き)
XAML
ViewModel+ModelClass
Codebehind
*.cs
<ContentPage> <Button Command="{Binding UpdateCommand}“ CommandParameter="..."/>
var vm = new MyItem();this.BindingContext = vm;
this.UpdateCommand = new Command<string>((param) => { });
イベントの場合
XAML
ViewModel+ModelClass
Codebehind
*.cs
<ContentPage> <Button Click="OnButtonClicked"/>
void OnButtonClicked(object sender, EventArgs e) { vm.UpdateCommand(); }Orbtn.Click += (s,e) => { vm.UpdteCommand(); }
ルールを決めればどちらでも良い
シーケンス図
XAML ViewModelCodebehin
d*.cs
Binding
Execute
Event
Create
Action
MVVM の得意なところ汎用ではない道具は何に特化しているのか?
View をプラットフォーム依存にする
View ViewModel Model
XAML による実装WPF
Windows StoreWindows PhoneXamarin.Forms
プラットフォーム非依存のライブラリにできる
ライブラリPCL
Shared Project
※ ただし、活用範囲が狭ければ、 ライブラリにする必要はない
ViewModel を TDD 可能にする
View ViewModel Model
プラットフォーム非依存にすることにより、
TDD で自動テストが可能になる
View
View の切り替えが可能
View ViewModel Model
View
動的に View を切り替えることが可能
※ ただし、現状の XAML(MS/Xamarin.Forms ) では、動的切り替えはあまり考えられてない。
別の MVVM フレームワークの利用
View ViewModel Model
インターフェースSystem.ComponentModel.INotifyPropertyChanged
System.Windows.Input.Icommand
が同じなので、他の MVVM フレームワークと互換性がある
WPF の MVVM, MvvmCross, Prism, Xamarin.Forms など
ViewModel のコツ
プラットフォーム非依存にするView を呼ばないプラットフォーム固有の機能を使わない
同時にデメリットでもある
Xamarin.Forms 特有の MVVMてこの原理を使って効果を最大化する
Xamarin.Forms の MVVM
WPF/Windows Store App の XAML と同じように作れるINotifyPropertyChanged 、 IComman
d のインターフェースがあるデザインビューがないので直打ち
Try&Error がやり辛い
単体のバインド
<StackLayout> <Label Text=" 設置場所情報 " /> <Label Text=" 施設名 " Font="Small" /> <Label Text="{Binding Item.LocationName}" /> <Label Text=" 住所 " Font="Small"/> <Label Text="{Binding Item.FullAddress}" />
this.SetBinding(Label.TextProperty, Item.Name)
ModelView のクラス構造を入れ子にできる
コレクションのバインド
<ListView ItemsSource="{Binding Items}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout> <Label Text="{Binding LocationName}" />
listView.ItemsSource = Items
セル指定
セル内のレイアウトを作成
セルにバインド
数値フォーマットの表示
< Label Text="{Binding Count,StringFormat='{0}'}"/>
int 型
String.Format に変換適宜フォーマットするコンバータ利用
Xamarin.Forms.IValueConverter
その他の Xamarin.Forms のバインド機能
Part 4. Data Binding Basicshttp://developer.xamarin.com/guides/cross-
platform/xamarin-forms/xaml-for-xamarin-forms/data_binding_basics/
Part 5. From Data Bindings to MVVMhttp://developer.xamarin.com/guides/cross-
platform/xamarin-forms/xaml-for-xamarin-forms/data_bindings_to_mvvm/
AEDSearch によるデモ
TMPuzzleXForms によるデモ
MVVM の限界限界があるからこそ、最大限の利用が可能。それ以後は場を変える。
画面遷移の不都合
ViewModel がプラットフォーム非依存のため、 View (プラットフォーム依存)ができない / やりにくい。this.Navigation.PushAsync素直に View のイベントを使う
複雑なイベント処理が ICommand ではやりづらい
ICommand では静的なパラメータのみ利用可能<Button Command=“…”
CommandParameter=“…” />素直にイベントを利用コードビハイドから ViewModel へ渡す
GoF Command パターン
大量の命令 ( コマンド ) を一括で扱うSystem.Windows.Input.ICommandSendMessageEevntHandler
パラメタの型が失われる欠点
その他の欠点
プロパティ伝播が過敏非同期 (async/await) が使えないView での不意な重たい処理に弱い
コレクションの変更に過敏プラットフォーム依存データが扱いにくい
と云う限界を知って MVVM を使う
XAML+ イベントの使い分けRx の利用C++, F# でパイプの利用動的 XAML ロード
参考文献
Cross-Platform User Interfaces with Xamarin.Formshttp://developer.xamarin.com/guides/cross-platform/xamarin-forms/
MvvmCrosshttps://github.com/MvvmCross
Prism 5.0 for .NET 4.5http://compositewpf.codeplex.com/releases/view/117297
Reactive Alliancehttp://www.reactivealliance.com/
AED Opendata Search Samplehttp://code.msdn.microsoft.com/AED-Opendata-Search-Sample-117dfafc
moonmile/TMPuzzleXFormshttps://github.com/moonmile/TMPuzzleXForms
moonmile/XFormsPreviewerhttps://github.com/moonmile/XFormsPreviewer