Xamarin.iOS+MvvmCrossでstoryboardを使う方法 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5814
以前、書いたのですが、バージョンが上がって微妙に動きが異なっているので、メモ書きしておきます。
サンプルコードは http://1drv.ms/1CeHWYp からダウンロードができます。
MvvmCross のサンプルコードを storyboard 対応にする
Tip Calc The Core Project
https://github.com/MvvmCross/MvvmCross/wiki/Tip-Calc—The-Core-Project
Tip Calc A Xamarin.iOS UI project ・ MvvmCross/MvvmCross Wiki
https://github.com/MvvmCross/MvvmCross/wiki/Tip-Calc-A-Xamarin.iOS-UI-project
TipCalc.Core の中身
ViewModel は MvxViewModel クラスを継承して作ります。ここのバインドは、INotiryPropertyChanged を実装していればよいので、何で作っても良いはずです。
プロパティの変更時に、RaisePropertyChanged で変更通知をします。
public class TipViewModel : MvxViewModel
{
private readonly ICalculation _calculation;
public TipViewModel(ICalculation calculation)
{
_calculation = calculation;
}
public override void Start()
{
_subTotal = 100;
_generosity = 10;
Recalcuate();
base.Start();
}
private double _subTotal;
public double SubTotal
{
get { return _subTotal; }
set { _subTotal = value; RaisePropertyChanged(() => SubTotal); Recalcuate(); }
}
App.cs の中身は、空っぽでも動きます…と思ったけど、Calculation のインスタンスだけ作らないとダメです。この部分は、Calc 部分を ICalc で作っているので、こうなっているので、特に作らなければ App() の中身は空でも大丈夫です。
public App()
{
Mvx.RegisterType<ICalculation, Calculation>();
// Mvx.RegisterSingleton<IMvxAppStart>(new MvxAppStart<TipViewModel>());
}
RegisterSingleton を使うとシングルトンで作られてしまい、都合が悪いことが多いので、UI プロジェクトのほうで作ります。
TipCalc.UI.Touch の中身
Setup.cs の中身はほとんど空っぽです。
public class Setup : MvxTouchSetup
{
public Setup(MvxApplicationDelegate appDelegate, IMvxTouchViewPresenter presenter)
: base(appDelegate, presenter)
{
}
protected override Cirrious.MvvmCross.ViewModels.IMvxApplication CreateApp()
{
return new App();
}
}
AppDelegate.cs の中身は、Window プロパティを残して、FinishedLaunching だけオーバーライドします。
内部で window を作っているサンプルコードもあるのですが、別のところから Window プロパティを参照することができるので、元の状態で残したほうがベターです。
以前と違って、Setup の引数が変わっているので、MvxTouchViewPresenter オブジェクトを作って引き渡します。
まあ、Setup 自体を変えてしまってもいいのですが。
[Register("AppDelegate")]
public partial class AppDelegate : MvxApplicationDelegate
{
// class-level declarations
public override UIWindow Window
{
get;
set;
}
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
var presenter = new MvxTouchViewPresenter(this, Window);
var setup = new Setup(this, presenter);
setup.Initialize();
return true;
}
}
TipCalc.UI.TouchViewController.cs の ViewModel は、MvxViewController を継承するように変更して、ViewDidLoad メソッドの中身だけ変更します。
base.ViewDidLoad で元のメソッドを呼び出す前に、MvxViewModelRequest オブジェクトを作らないといけません。この引数が変更になっていて、ViewModel のクラス名(ここでは TipViewModel )を渡します。
CreateBindingSet は拡張メソッドなので、
using Cirrious.MvvmCross.Binding.BindingContext;
することを忘れずに…いつもあれ?ってなるので。
public partial class TipCalcUITouchViewController : MvxViewController
{
public TipCalcUITouchViewController(IntPtr handle)
: base(handle)
{
}
public new TipViewModel ViewModel
{
get { return (TipViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
public override void ViewDidLoad()
{
this.Request = new MvxViewModelRequest(typeof(TipViewModel), null, null, new MvxRequestedBy());
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
var set = this.CreateBindingSet<TipCalcUITouchViewController, TipViewModel>();
set.Bind(labelTip).To(vm => vm.Tip);
set.Bind(textSubTotal).To(vm => vm.SubTotal);
set.Bind(sliderGene).To(vm => vm.Generosity);
set.Apply();
}
}
Bind でコントロールを指定して、To で ViewModel のプロパティと結びつけます。いわゆる Binding の Path は .For( c => c.Text) で明示的に指定もできますが省略可能です(デフォルトプロパティを内部で持っていると思われる)。
実行結果
こんな風にスライダーを動かすと、ラベルの数値が変化します。
サンプルコード
サンプルはこちら
http://1drv.ms/1CeHWYp

