LoginSignup
6
6

More than 5 years have passed since last update.

Using MvvmCross in Xamarin.Mac

Posted at

Overview

毎度毎度おまじないが多いので,ここできっちりまとめておきます。
MvvmCross v3.1.1時点ではXamarin.Mac向けにはNuSpecが書かれておらず,NuGet経由で組み込むことはできません。Xamarin.Mac+MvvmCrossでアプリ開発を始める準備の準備(2014年3月)を参考に,事前にXamarin.Mac向けライブラリを準備してください。

Project

 Coreプロジェクトは省略します。PCLでもNonPCLでもかまいません。
 Xamarin.Macプロジェクトを作成しますが,Xamain Studio 4.2.3時点ではソリューションにいきなりXamarin.Macプロジェクトを追加するとXamMacへの参照ができずにMonoMacネームスペースを解決できなくなりますので, MonoMacプロジェクトを作ってMigrateする 必要があります(新規ソリューションと合わせ技なら大丈夫みたいです)。
 Coreプロジェクトと,以下のライブラリ参照を追加しておきます。

  • Cirrious.CrossCore
  • Cirrious.CrossCore.Mac
  • Cirrious.MvvmCross.Binding
  • Cirrious.MvvmCross.Binding.Mac
  • Cirrious.MvvmCross
  • Cirrious.MvvmCross.Localization
  • Cirrious.MvvmCross.Mac
  • System.Windows

 さらにターゲットフレームワークをMono/.NET 4.5に設定します。またXamarin.MacでMvvmCrossを使う際のWorkaround #1を参考に,リンカーの設定を変更しておいてください。
 ここで一度実行し,空のWindowが表示されるのを確認しておくのをお勧めします。うまくいかないときは潔くXamMacプロジェクトをまるっと削除し,最初からやり直してください。

Setup.cs

 Setup.csをプロジェクトルートに追加し,下記のように記述します。MyApp名前空間は適宜置き換えてください。

Setup.cs
using System;
using Cirrious.MvvmCross.Mac.Platform;
using Cirrious.MvvmCross.Mac.Views.Presenters;

namespace MyApp.UI.Mac
{
    public class Setup: MvxMacSetup
    {
        public Setup (MvxApplicationDelegate applicationDelegate, IMvxMacViewPresenter presenter)
            : base (applicationDelegate, presenter)
        {
        }

        protected override IMvxApplication CreateApp()
        {
            return new MyApp.Core.App();
        }
    }
}

AppDelegate.cs

 最初から作られているAppDelegateにも記述が必要になります。

AppDelegate.cs
using MonoMac.Foundation;
using MonoMac.AppKit;
using Cirrious.MvvmCross.Mac.Views.Presenters;
using Cirrious.CrossCore;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.Mac.Platform;

namespace MyApp.UI.Mac
{
    public partial class AppDelegate : MvxApplicationDelegate
    {
        MainWindowController mainWindowController;

        public AppDelegate()
        {
        }

        public override void FinishedLaunching(NSObject notification)
        {
            mainWindowController = new MainWindowController();

            var presenter = new MvxMacViewPresenter(this, mainWindowController.Window);
            var setup = new Setup(this, presenter);
            setup.Initialize();

            var startup = Mvx.Resolve<IMvxAppStart>();
            startup.Start();

            mainWindowController.Window.MakeKeyAndOrderFront(this);
        }

        public override bool ApplicationShouldTerminateAfterLastWindowClosed(NSApplication sender)
        {
            return true;
        }
    }
}

もちろんApplicationShouldTerminateAfterLastWindowClosedオーバーライドは任意です。

Views

プロジェクトにViewsフォルダを追加し,Cocoa View with Controllerを追加します。名前はビューモデルに合わせてください。
kobito.1394170307.530577.png

FirstView.cs

 することは多くありません。ベースクラスをMvxViewに変更します。

FirstView.cs
// (省略)
namespace MyApp.UI.Mac
{
    public partial class OperationView : MvxView
    {
        #region Constructors
        // (以下略)

FirstViewController.cs

 こちらではベースクラスをMvxViewControllerに変更し,ViewModelプロパティを型強制しておきます。遺憾ながらWPFとは異なり,ViewModelに直接アクセスしないとならない場面が多々あります。

FirstViewController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using MonoMac.Foundation;
using MonoMac.AppKit;
using Cirrious.MvvmCross.Mac.Views;
using MyApp.Core.ViewModels;

namespace MyApp.UI.Mac
{
    public partial class FirstViewController : MvxViewController
    {
        // Constructorは省略します
        #region Constructors

        //strongly typed view accessor
        public new FirstView View
        {
            get
            {
                return (FirstView)base.View;
            }
        }

        public new FirstViewModel ViewModel
        {
            get
            {
                return (FirstViewModel)base.ViewModel;
            }
        }
    }
}

FirstView.xib

 Xcodeを使って適当にコントロールを配置し,アウトレットを接続します。接続するのはFirstViewController.hです。接続先に注意してください。
Screen Shot 2014-03-07 at 2.41.13 PM.png
 テキストボックスとラベルを配置し,HelloBox, HelloLabelと名前をつけました。
 XcodeからXamarin Studioに切り替えてしばらくすると変更が同期されます。Xamarin Studioを複数起動しているとうまく同期できなくなるので注意してください。

Binding

 FirstViewController.hの変更がうまく同期されたら,データを紐付けていきます。CoreプロジェクトのGreetingプロパティをテキストボックスとラベルにバインドし,即時変更されることを確かめましょう。
 バインディングセットを記述するのはWindowDidLoadオーバーライドメソッドです。

FirstViewController.cs
using Cirrious.MvvmCross.Binding.BindingContext;

public override void ViewDidLoad ()
{
    base.ViewDidLoad();

    var set = this.CreateBindingSet<FirstViewController, FirstViewModel>();
    set.Bind(HelloBox)
        .For("StringValue")
        .To(vm => vm.Greeting);
    set.Bind(HelloLabel)
        .For(c => c.StringValue)
        .To(vm => vm.Greeting)
        .OneWay();
    set.Apply();
}

 set.Bind(コントロール).For(バインド先プロパティ).To(ビューモデル側プロパティ); が基本です。最後にApplyを必ず呼んでください。バインド先プロパティの指定は式木でも文字列でもかまいません。OneWayなどもデフォルトでよければ指定の必要はありません。ValueConverterをかます場合は.WithConversion(コンバータ名)で指定します。
 ここまでできたら実行します。うまくいっていればテキストボックスに入力した値が即時反映されるはずです。MacのNSTextFieldはUpdateSourceTriggerOnPropertyChangeになっています。
Screen Shot 2014-03-07 at 2.49.53 PM.png

Conclusion

 紆余曲折を経てここにたどり着きました。NuGetでできればこんなことは悩まないですが,最低限動かすのに必要な設定を手で書けた方が理解も早いはずです。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6