[Xamarin.Mac] データバインディングでテーブルビューを表示してみました

2020.11.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

CX事業本部の平内(SIN)です。

Xamarin.Macを使用すると、C#でネイティブなMacのアプリが作成可能です。 ここでは、私自身がXamarin.Macに入門して学習した事項を覚書として書かせて頂いています。

今回は、データバインディングを使用して、テーブルビューを表示してみました。

データバインディングを使用することで、DataSource及び、Delegateの準備は、必要なくなります。

2 Productクラス

データの基本クラスとなる商品クラスは、前回、定義したものをそのまま利用します。

商品(Product)クラスは、名前(Name)と価格(Price)がプロパティとして公開されています。

[Register("Product")]
public class Product : NSObject {

    private string _name;
    private int _price;


    public Product(string name, int price) {
        _name = name;
        _price = price;
    }

    [Export("Name")]
    public string Name {
        get {
            return _name;

        }
        set {
            WillChangeValue("Name");
            _name = value;
            DidChangeValue("Name");
        }
    }

    [Export("Price")]
    public int Price {
        get { return _price; }
        set {
            WillChangeValue("Name");
            _price = value;
            DidChangeValue("Name");
        }
    }
}

3 Productsクラス

ViewControllerで商品データの配列を定義し、公開しているコードは、以下のとおりです。

データの配列は、NSMutableArrayである必要があります。そして、データ配列は、ViewControllerのプロパティとして、[Export("Products")] でObjective-Cに公開されています。

また、データ配列をコントローラーから操作するためのメソッドも定義して公開します。

  • addObject: オブジェクトを追加
  • insertObject:in{class_name}ArrayAtIndex: インデックス位置にオブジェクト挿入
  • removeObjectFrom{class_name}ArrayAtIndex: インデックス位置のオブジェクトを削除
  • set{class_name}Array: 置き換え
public partial class ViewController : NSViewController {

    // 商品(Product)クラスの配列を定義
    private NSMutableArray _products = new NSMutableArray();

    // 商品(Product)クラスを公開
    [Export("Products")]
    public NSMutableArray Products {
        get { return _products; }
        set {
            WillChangeValue("Products");
            _products = value;
            DidChangeValue("Products");
        }
    }

    // 商品(Product)クラスの操作(追加)
    [Export("addObject:")]
    public void AddProduct(Product product) {
        WillChangeValue("Products");
        _products.Add(product);
        DidChangeValue("Products");
    }

    // 商品(Product)クラスの操作(挿入)
    [Export("insertObject:inPersonModelArrayAtIndex:")]
    public void InsertProduct(Product product, nint index) {
        WillChangeValue("Products");
        _products.Insert(_products, index);
        DidChangeValue("Products");
    }

    // 商品(Product)クラスの操作(削除)
    [Export("removeObjectFromPersonModelArrayAtIndex:")]
    public void RemoveProduct(nint index) {
        WillChangeValue("Products");
        _products.RemoveObject(index);
        DidChangeValue("Products");
    }

    // 商品(Product)クラスの操作(置き換え)
    [Export("setPersonModelArray:")]
    public void SetProduct(NSMutableArray array) {
        WillChangeValue("Products");
        _products = array;
        DidChangeValue("Products");
    }

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

        // 商品(Product)クラスの初期化
        AddProduct(new Product("AAA", 100));
        AddProduct(new Product("BBB", 110));
        AddProduct(new Product("CCC", 300));
        AddProduct(new Product("DDD", 220));

    }

// ・・・略・・・

4 バインディング

ViewControllerで公開されたデータ配列がTableViewに展開されるまでのバインディングは、以下の流れになります。

NSMutableArray > ArrayController >TableView > TableViewCell

(1) ArrayController

下記では、ViewControllerにTableViewを追加し、制約でウインドウいっぱいに表示しています。

そして、ViewControllerArray Controllerを追加してます。

Array Controllerは、ViewControllerProductsにバインドします。

(2) Table View

Table Viewは、上記のArray Controllerへバインドします。

(2) Table View Cell

最終的に、セルは、Table View Cellにバインドし、Model Key Pathで商品クラスのプロパティを指定しています。

  • 最初のカラムは、Nameにバインド

  • 2つめのカラムは、Priceにバインド

5 動作確認

実行してみると、商品データの配列が、表示されていることを確認できます。

6 最後に

今回は、データバインディングで、テーブルビューを表示してみました。

この仕組みを利用すると、DataSource / Delegate を準備する必要はなくなります。

C#では、多重継承が出来ないため、データの主体となっているビューコントローラーと表示のための、DataSource、Dalegateと言った複数クラスに分散してしまうことを考えると、データバインドでViewControllerに表示用の処理をまとめるやり方は、状況によっては、スッキリするかも知れません。

ただし、データ操作は、連携用に定義したメソッドの利用が必須です。直接操作したりすると、コントロールに反映されず、データと表示が矛盾することになるので注意が必要だと思います。