Xamarin.MacのNSTableViewでNSTableViewSourceを使う

提供: MonoBook
2015年3月27日 (金) 02:07時点における153.220.119.198 (トーク)による版 (→‎実装1)
ナビゲーションに移動 検索に移動

実装1:Cell Base

Xamarin.MacにはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。

列となるデータを準備する

まずはソースの元(テーブルの1行)となるクラスを用意する。

    public class Study
    {
        public string Id { get; set; }
        public string Name { get; set; }
    }

行となるデータソースを準備する

次にデータソースを用意する。 NSTableViewSourceクラスを継承してGetRowCountメソッドとGetObjectValueメソッドをオーバーライドすることで利用可能な状態となる。

この例ではNSTableColumnクラスのIdentifierプロパティの値と、前述のStudyクラスの各プロパティ名でマッピングを行っている。 NSTableColumnクラスのIdentifierプロパティはInterface Builderで設定した。

また、別途IList<>インターフェースを実装しておくとLINQで操作できたり色々便利だった。無くてもよい。

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;

    using Foundation;
    using AppKit;

    public class StudyTableViewSource : NSTableViewSource, IList<Study>
    {
        IList<Study> _items = new List<Study>();

        public override int GetRowCount(NSTableView tableView)
        {
            return _items.Count;
        }

        public override NSObject GetObjectValue(NSTableView tableView, NSTableColumn tableColumn, int row)
        {
            if (tableColumn.Identifier == null)
            {
                return null;
            }

            var item = _items[row];
            var type = typeof(Study);
            var prop = type.GetProperty(tableColumn.Identifier, BindingFlags.Public | BindingFlags.Instance);
            if (prop == null)
            {// そんな名前のプロパティはない
                return null;
            }

            var val = prop.GetValue(item);
            if (val == null)
            {// 空っぽですわ
                return null;
            }

            var ret = new NSString(val.ToString());
            return ret;
        }

        //  〜以下略〜
    }

使ってみる

早速使ってみる。

この例では

  • Interface BuilderでMainWindow.xibファイルを開き、
  • NSTableViewを貼り付け、
  • Content Modeを「Cell Based」に設定し
  • アウトレットは「_studyTableView」という名前にしておいた。
    public partial class MainWindowController : NSWindowController
    {
        // 〜前略〜

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

            var studies = new StudyTableViewSource();
            studies.Add(new Study { Id = "A1", Name = "B1" });
            studies.Add(new Study { Id = "A2", Name = "B2" });
            studies.Add(new Study { Id = "A3", Name = "B3" });
            studies.Add(new Study { Id = "A4", Name = "B4" });
            _studyTableView.Source = studies;
        }
    }

なんと、この状態で実行するとテーブルの表示はされるが、クリックしても行選択ができない。

行選択

これで良いのか知らんが以下で行選択が出来るようになった。

        public override void WindowDidLoad()
        {
            // 〜前略〜

            _studyTableView.Activated += (object sender, EventArgs e) => {
                var tableview = (NSTableView)sender;
                int clickedrow = (int)tableview.ClickedRow;
                tableview.SelectRow(clickedrow, false);
                tableview.ScrollRowToVisible(clickedrow);
            };
        }

セル編集

Interface Builderを開き、各カラムに「Editable」のチェックを入れる(最初から入っていると思う)。 設定対象はカラムでありセルじゃないよ(Identity Inspectorを開くとクラスがNSTableColumnとなってるやつ)。

多分こんな構造になっているはず

  • NSTableView
    • NSTableColumn ←これに「Editable」を設定する
      • NSTextFieldCell

次にデータソースの以下のメソッドをオーバーライドし「true」を返すようにする。 前述のEditableのチェックをしておくことでこのメソッドが呼ばれるようになり、このメソッドでtrueを返すと実際に編集が可能な状態となるようだ。

    public class StudyTableViewSource : NSTableViewSource, IList<Study>
    {
        // 〜〜〜省略〜〜〜

        public override bool ShouldEditTableColumn(NSTableView tableView, NSTableColumn tableColumn, int row)
        {
            return true;
        }

関連項目

参考文献