[Xamarin.Mac] テーブルビューを表示してみました

2020.11.17

1 はじめに

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

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

今回は、テーブルビューを確認してみました。

2 TableViewの配置

Interface Builderで、メインとなるビューTableViewを配置し、ウインドウいっぱいに表示されるように制約を追加します。

また、AssistantエディタでViewController.hを開いてOutletを接続します。 ※接続するコントロールがNSTableViewになっていることに注意が必要です。

各カラムのタイトルや、デフォルトの幅は、プロパティで設定できます。

この状態で実行すると、下記のような表示になります。

3 データクラス

表示するデータの構造を定義するため、「ファイル」-「新しいファイル」-「General」-「空のクラス」で新規にクラス(Person)を作成します。

クラスPersonは、超簡単な個人の情報で、名前(Name)と年齢(Age)だけを保持します。

public class Person {

    public string Name { get; set; } = "";
    public int Age { get; set; } = 0;

    public Person(string name, int age) {
        this.Name = name;
        this.Age = age;
    }
}

4 DataSourceとDelegate

TableViewにデータを表示するには、DataSourceとDelegateの仕組みが必要です。

(1) DataSource

NSTableViewDataSourceを継承したクラス(TableViewDataSource)を追加し、先のデータ(Person)のリストを保持します。

また、NSTableViewDataSourceGetRowCountをオーバーライドし、データの個数を返すようにします。

using System;
using System.Collections.Generic;
using AppKit;

namespace Sample001 {
    public class TableViewDataSource : NSTableViewDataSource {

        public List<Person> Persons = new List<Person>();

        public TableViewDataSource(){
        }

        public override nint GetRowCount(NSTableView tableView) {
            return Persons.Count;
        }
    }
}

(2) Delegate

NSTableViewDelegateを継承したクラス(TableViewDelegate)を追加し、変数でDataSourceを定義しコンストラクタで初期化します。

また、NSTableViewDelegateGetViewForItemをオーバーライドし、セルの生成と値の設定を行います。

GetViewForItemは、1つのセルを描画する度に呼ばれますが、返すデータは、rowで行、タイトルでカラムを識別しています。

using System;
using AppKit;

namespace Sample001 {
    public class TableViewDelegate : NSTableViewDelegate {

        private string identifier = "cell";
        private TableViewDataSource DataSource;

        public TableViewDelegate(TableViewDataSource dataSource) {
            this.DataSource = dataSource;
        }

        public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row) {

            NSTextField view = (NSTextField)tableView.MakeView(identifier, this);
            if(view == null) {
                view = new NSTextField();
                view.Identifier = identifier;
                view.BackgroundColor = NSColor.Clear;
                view.Bordered = false;
                view.Selectable = false;
                view.Editable = false;
            }

            switch(tableColumn.Title) {
                case "Name":
                    view.StringValue = DataSource.Persons[(int)row].Name;
                    break;
                case "Age":
                    view.StringValue = DataSource.Persons[(int)row].Age.ToString();
                    break;
            }

            return view;
        }
    }
}

5 TreeViewの初期化

ViewControllerAwakeFromNibをオーバーライドし、DataSourceの初期化と、コントロールへの紐付けを行います。

public partial class ViewController : NSViewController {

    //・・・・・・・略・・・・・・

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

        var DataSource = new TableViewDataSource();
        DataSource.Persons.Add(new Person("Taro", 20));
        DataSource.Persons.Add(new Person("Jiro", 18));
        DataSource.Persons.Add(new Person("Hanako", 14));

        TableView.DataSource = DataSource;
        TableView.Delegate = new TableViewDelegate(DataSource);
    }
}

ここまでの作業で、表示は以下のようになりました。

6 最後に

今回は、テーブルビューについて確認してみました。

見た目の表現は、インターフェースビルダーのプロパティで、殆ど設定可能です。

また、TableViewの各セルは、DelegateGetViewForItem()で返すことで構成されています。今回は、NSTextFieldを返してテキストを表示していますが、要求される型はNSViewですので、自由に表現が可能でしょう。