[Xamarin.Mac] View Controller間でデータを受け渡すには

前回の記事では、View Controllerをコードから表示する方法について紹介しました。

今回は、View Controller間でのデータの受け渡し方法について見ていきましょう。

1.メインウィンドウの作成

はじめに新規でプロジェクトを作成して、メインウィンドウにButtonを1つ、その下にText Fieldを1つ貼り付けます。

続いて、貼り付けたButtonのアクション接続を作成します。アクション名は「showSubView」とします。

次に、貼り付けたText Fieldのアウトレット接続を作成します。接続名はfirstTextとしてください。

アクション接続とアウトレット接続の作成方法については「シンプルなアプリを作ってみよう 〜アクションとアウトレット〜」を参照ください。

作成したアクション接続とアウトレット接続のコードを以下に示します。

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>


@interface ViewController : NSViewController {
    NSTextField *firstText;
}
- (IBAction)showSubView:(id)sender;
@property (assign) IBOutlet NSTextField *firstText;

@end

2.サブウィンドウの作成

続いて、もう1つView Controllerを配置します。

このView ControllerにもButtonとText Fieldを配置します。

次にView Controllerを選択してCustom Classに「SecondViewController」と入力して[return]キーを押し、[command]+[s]で上書き保存をします。この操作によってサブウィンドウ用のクラスが作成されます。このクラスはNSViewControllerを継承しています。

次にアシスタントエディタでSecondViewController.hを開いておき、今配置したText Fieldのアウトレット接続を作成します。アウトレット接続の名前はsecondTextとしてください。

またButtonのアクション接続も作成します。アクション接続名はsubViewCloseとします。

SeconViewController.hのコードは以下のようになります。

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

@interface SecondViewController : NSView {
    NSTextField *secondText;
}
@property (assign) IBOutlet NSTextField *secondText;
- (IBAction)subViewClose:(id)sender;

@end

ここまでできたら[command]+[s]を押して、Visual Studioへ戻ります。

3.セグエの作成

続いてセグエを作成しましょう。メインウィンドウからサブウィンドウに向かってドラッグ&ドロップし、セグエを作成します。表示されたManual SegueのダイアログではModalを選択することとします。

次に作成したSegueを選択して「MySegue」という名前を付けます。あとで、この名前でコードからサブウィンドウを開けるように作成します。

4.メインウィンドウのコードを作成する

続いてメインウィンドウのコードを作成するのですが、その前にサブビュー側でメインウィンドウから渡された値を受け取ることができるプロパティを作成しておきましょう。

Visual StudioでSecondViewController.csを開いて、以下のように、TextValueというプロパティを追加します。

// This file has been autogenerated from a class added in the UI designer.

using System;

using Foundation;
using AppKit;

namespace WindowSample5
{
  public partial class SecondViewController : NSViewController
  {
    // メインウィンドウから受け取る値用のプロパティ
    public string TextValue { get; set; }

    public SecondViewController (IntPtr handle) : base (handle)
    {
    }
  }
}

次に、ViewController.csを開いてメインウィンドウのコードを以下のように入力します。

using System;

using AppKit;
using Foundation;

namespace WindowSample5
{
  public partial class ViewController : NSViewController
  {
    public ViewController(IntPtr handle) : base(handle)
    {
    }

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

      // Do any additional setup after loading the view.
    }

    public override NSObject RepresentedObject
    {
      get
      {
          return base.RepresentedObject;
      }
      set
      {
          base.RepresentedObject = value;
          // Update the view, if already loaded.
      }
    }

    // ここから追加コード

    // Buttonクリック時の処理
    partial void showSubView(NSObject sender)
    {
      // Segueでサブビューを表示
      PerformSegue("MySegue", this);
    }

    // Segueでサブウィンドウが開かれる前に実行されるメソッド
    public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
    {
      base.PrepareForSegue(segue, sender);

      // サブウィンドウのインスタンスを取得
      SecondViewController sv = segue.DestinationController as SecondViewController;
      // サブウィンドウのプロパティに値をセット
      sv.TextValue = this.firstText.StringValue;
    }

    // サブウィンドウから呼び出してメインウィンドウのText Fieldに値をセットするメソッド
    public void SetTextValue(string textValue)
    {
        this.firstText.StringValue = textValue;
    }
  }
}

Buttonには、showSubView というアクション接続を作成したので、partial void showSubView というメソッドを追加しています。このめそっどの中では PerformForSegue メソッドを使用してサブウィンドウを開きます。

サブウィンドウを開く前に値を渡したいので、PrepareForSegue というメソッドをオーバーライドして追加しています。このメソッドは、セグエが実行される前に起動して処理が行われます。よってメソッドの中では、サブウィンドウのインスタンスを取得して、サブウィンドウのプロパティである TextValue にメインウィンドウの Text Field の値を設定しています。

最後に、サブウィンドウからメインウィンドウへ値をセットできるようにするために SetTextValue というメソッドを追加しています。引数で受け取った値をメインウィンドウのText Fieldに設定しています。

5.サブビューのコードを作成する

最後ににサブビュー側のコードを作成しましょう。

ソリューションエクスプローラーで SecondViewController.cs をダブルクリックして開き以下のようにコードを入力します。

// This file has been autogenerated from a class added in the UI designer.

using System;

using Foundation;
using AppKit;

namespace WindowSample5
{
  public partial class SecondViewController : NSViewController
  {
    // メインウィンドウから受け取る値用のプロパティ
    public string TextValue { get; set; }

	public SecondViewController (IntPtr handle) : base (handle)
	{
	}

    // ここから追加コード
    public override void ViewDidLoad()
    {
      base.ViewDidLoad();

      // Text Fieldにメインウィンドウから受け取った値をセット
      this.secondText.StringValue = this.TextValue;
    }

    partial void subViewClose(NSObject sender)
    {
      // メインウィンドウのインスタンスを取得
      ViewController vc = this.PresentingViewController as ViewController;
      // メインウィンドウのメソッドを呼び出して、サブウィンドウのText Fieldの値を渡す
      vc.SetTextValue(this.secondText.StringValue);
      // サブウィンドウを閉じる
      this.View.Window.Close();
    }
  }
}

オーバーライドした ViewDidLoad は、画面が開かれたときに初期化をするメソッドです。ここでは、メインウィンドウから受け取った値が入っている TextValue プロパティを、Text Fieldに設定しています。これによりサブウィンドウが開いたときに、メインウィンドウから受け取った値が Text Field に表示されます。

subViewClose というメソッドは Button がクリックされたときに実行されるメソッドです。この中ではメインウィンドウのインスタンスを取得して、SetTextValue というメソッドを使用して、サブウィンドウのText Fieldの値を渡しています。最後に Close メソッドを実行してサブウィンドウを閉じます。

6.実行してみよう

それでは実行して確認をしてみましょう。

メインウィンドに「メインウィンドウの値」と入力してButtoonをクリックすると、サブウィンドウが表示されText Fieldには「メインウィンドウの値」と表示されます(上がメインウィンドウ、下がサブウィンドウの図です)。

次にサブウィンドウのText Fieldに「終了」と入力してButtonをクリックすると、サブウィンドウが閉じられてメインウィンドウのText Fieldに「終了」が表示されます(上がサブウィンドウ、下がメインウィンドウの図です)。

 

[Xamarin.Mac] コードからView Controllerを表示する

これまでの記事ではAction Segueを使用して他のView Controllerを表示する方法を見てきました。

今回は、コードを記述してメインのビューから他のビューを表示する方法を見ていきます。

1.事前準備

はじめに新規でプロジェクトを作成して、メインウィンドウにButtonを1つ貼り付けます。

2.サブウィンドウの追加とセグエの設定

続いて新規でView Controllerを1つ追加します。View Controllerを追加したら、既存のView Controllerを追加したView Controllerにドラッグ&ドロップしてセグエを作成します(下図参照)。

続いてManual Segueのダイアログが表示されるので、今回はModalを指定することとします。

次に、セグエを選択して名前(Identifier)を「mySegue」としてください。あとでこの名前を使用して、コードからサブウィンドウを開けるようにします。

3.アクション接続の作成

続いてメインウィンドウに配置した[Show sub view]のアクション接続を作成します。アクション名は「showSubView」としてください。

アクション接続の作成方法については「シンプルなアプリを作ってみよう 〜アクションとアウトレット〜」を参照ください。

ここまでできたら、[command]+[s]で保存をして、Visual Studioへ戻ります。

4.コードからView Controllerを表示する

ViewController.csを開いて以下のコードを追加してください。このメソッドは、先ほど作成したアクションになります。

PerformSegueというメソッドは、セグエを起動するためのメソッドで、第1引数にセグエの名称を、第2引数にはthisを渡します。引数に渡したMySegueは2つ目のView ControllerをModalで開くようにしたので、[Show sub view]ボタンがクリックされると2つめのView Controllerが表示されます。

partial void showSubView(NSObject sender)
{
    PerformSegue("MySegue", this);
}

以上で完成です。実際に実行して動作を確認してください。

[Xamarin.Mac] サブウィンドウを閉じる

前回の記事では、セグエを使用してサブウィンドウを表示する方法を紹介しました。

今回は、サブウィンドウを閉じる方法を見ていきます。

1.事前準備

事前準備として、新規でプロジェクトを作成し、メインウィンドウにButtonを配置します。

続いて、サブウィンドウとして新しくView Controllerを追加しを1つ追加します。

最初に配置したButtonを[control]を押しながら、もう1つのView Controllerへドラッグ&ドロップし、Action Segueで「Sheet」を選択します(詳細な手順については前回の記事を参照してください)。

2.サブウィンドウの設定

次にサブウィンドウにButtonコントロールを配置して、閉じることができるように作成していきます。

はじめにButtonを追加し、テキストを「Close」に変更してください。

続いて[Close]ボタンを[control]キーを押しながらドラッグし「First Responder」へドロップします。

First Responderは、アプリケーションが起動中に最初に受け取るオブジェクトを表しています。ここでいうオブジェクトとはユーザーからのマウス操作やキーボード操作などのイベントのことです。First responderがイベントを受け取ったとしても、そのイベントウに応じられない場合もあります。このような場合は、その上位階層のオブジェクトへと順次送られて処理がされます。上位階層でも応じることができない場合は、さらに上の階層へと送られ、どのオブジェクトも処理ができない場合には警告になるか破棄されます。このような仕組みをResponder chainと呼びます。

First Responderにドロップすると、設定可能なアクションの一覧が表示されるので、一覧からdissmissControllerを選択します。dissmissControllerとはウィンドウを閉じるアクションです。

きちんとcloseボタンに dissmissControllerが接続されているかを確認しましょう。

以上で[Close]ボタンをクリックしてサブウィンドウを閉じることができるようになります。実行して動作を確認してみましょう。

3.補足(First Responderの設定確認)

First Responderの設定確認方法について説明します。

First Responderをクリックし、Connection Inspectorを開きます。Receive Actionsの一覧で「dissmissController」と[close]ボタンが接続されていることを確認できます。

[close]ボタン側でも確認をすることができます。[close]ボタンを選択してConnection Inspectorを開きます。Sent Actionsに「dismissController」があることを確認しましょう。