最新版 |
編集中の文章 |
1行目: |
1行目: |
− | == 実装2:View Base == | + | ==実装1== |
− | [[Xamarin.Mac]]にはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。
| + | Xamarin.MacにはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。 |
| | | |
− | === 列となるデータを準備する === | + | ===準備=== |
| まずはソースの元(テーブルの1行)となるクラスを用意する。 | | まずはソースの元(テーブルの1行)となるクラスを用意する。 |
| <source lang="csharp"> | | <source lang="csharp"> |
12行目: |
12行目: |
| </source> | | </source> |
| | | |
− | === 行となるデータソースを準備する === | + | ===データソースの用意=== |
− | 次にデータソースを用意する。
| |
− | NSTableViewSourceクラスを継承してGetRowCountメソッドとGetViewForItemメソッドをオーバーライドすることで利用可能な状態となる。
| |
− | Cellベースでは「GetObjectValue」のところがViewベースでは「GetViewForItem」となっている。
| |
− | | |
− | この例ではNSTableColumnクラスのIdentifierプロパティの値と、前述のStudyクラスの各プロパティ名の簡易自動マッピングを行っている。NSTableColumnクラスのIdentifierプロパティはInterface Builderで設定した。
| |
− | | |
− | また、別途IList<>インターフェースを実装しておくとLINQで操作できたり色々便利だった。無くてもよい。
| |
− | | |
− | <source lang="csharp">
| |
− | public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row)
| |
− | {
| |
− | if (tableColumn.Identifier == null)
| |
− | {
| |
− | return null;
| |
− | }
| |
− | | |
− | var item = _items[(int)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;
| |
− | }
| |
− | | |
− | switch (tableColumn.Identifier)
| |
− | {
| |
− | | |
− | // CellベースではNSStringを返せばよかったが、ViewベースではNSView派生クラスを返さねばならない。
| |
− | // NSTableCellViewを返すとCellベースと同じような使用感となる。
| |
− | // カスタムセルを使用する場合は分岐するとよい。
| |
− | default:
| |
− | var cellView = (NSTableCellView)tableView.MakeView(tableColumn.Identifier, this);
| |
− | cellView.TextField.StringValue = val.ToString();
| |
− | return cellView;
| |
− | }
| |
− | | |
− | }
| |
− | </source>
| |
− | | |
− | あとはCellベースと同じ。
| |
− | | |
− | == 実装1:Cell Base ==
| |
− | [[Xamarin.Mac]]にはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。
| |
− | | |
− | === 列となるデータを準備する ===
| |
− | まずはソースの元(テーブルの1行)となるクラスを用意する。
| |
− | <source lang="csharp">
| |
− | public class Study
| |
− | {
| |
− | public string Id { get; set; }
| |
− | public string Name { get; set; }
| |
− | }
| |
− | </source>
| |
− | | |
− | === 行となるデータソースを準備する ===
| |
| 次にデータソースを用意する。 | | 次にデータソースを用意する。 |
| NSTableViewSourceクラスを継承してGetRowCountメソッドとGetObjectValueメソッドをオーバーライドすることで利用可能な状態となる。 | | NSTableViewSourceクラスを継承してGetRowCountメソッドとGetObjectValueメソッドをオーバーライドすることで利用可能な状態となる。 |
135行目: |
74行目: |
| * Interface BuilderでMainWindow.xibファイルを開き、 | | * Interface BuilderでMainWindow.xibファイルを開き、 |
| * NSTableViewを貼り付け、 | | * NSTableViewを貼り付け、 |
− | * Content Modeを「Cell Based」に設定し | + | * Content Modeを「View Based」に設定し、 |
| * アウトレットは「_studyTableView」という名前にしておいた。 | | * アウトレットは「_studyTableView」という名前にしておいた。 |
− |
| |
− | 構造
| |
− | *NSTableView → この例では、_studyTableViewインスタンス
| |
− | **NSTableColumn → この例では、これのIdentityと、Studyクラスのプロパティが一致したものに文字列を代入している
| |
− |
| |
| <source lang="csharp"> | | <source lang="csharp"> |
| public partial class MainWindowController : NSWindowController | | public partial class MainWindowController : NSWindowController |
163行目: |
97行目: |
| なんと、この状態で実行するとテーブルの表示はされるが、クリックしても行選択ができない。 | | なんと、この状態で実行するとテーブルの表示はされるが、クリックしても行選択ができない。 |
| | | |
− | ===行選択できるようにする=== | + | ===行選択=== |
| これで良いのか知らんが以下で行選択が出来るようになった。 | | これで良いのか知らんが以下で行選択が出来るようになった。 |
| <source lang="csharp"> | | <source lang="csharp"> |
177行目: |
111行目: |
| }; | | }; |
| } | | } |
− | </source>
| |
− |
| |
− | ===セルを編集できるようにする===
| |
− | Interface Builderを開き、各カラムに「Editable」のチェックを入れる(最初から入っていると思う)。
| |
− | 設定対象はカラムでありセルじゃないよ(Identity Inspectorを開くとクラスがNSTableColumnとなってるやつ)。
| |
− |
| |
− | 多分こんな構造になっているはず
| |
− | *NSTableView
| |
− | **NSTableColumn ←これに「Editable」を設定する
| |
− | ***NSTextFieldCell
| |
− |
| |
− | 次にデータソースの以下のShouldEditTableColumnメソッドをオーバーライドし「true」を返すようにする。
| |
− | 前述のEditableのチェックをしておくことでこのメソッドが呼ばれるようになり、このメソッドでtrueを返すと実際に編集が可能な状態となるようだ。
| |
− | <source lang="csharp">
| |
− | public class StudyTableViewSource : NSTableViewSource, IList<Study>
| |
− | {
| |
− | // 〜〜〜省略〜〜〜
| |
− |
| |
− | public override bool ShouldEditTableColumn(NSTableView tableView, NSTableColumn tableColumn, int row)
| |
− | {
| |
− | return true;
| |
− | }
| |
− | }
| |
− | </source>
| |
− |
| |
− | 上記のShouldEditTableColumnメソッドのみでは編集はできるが、編集終了後に値が反映されず、編集前の状態に戻ってしまう。
| |
− | そこで以下のSetObjectValueメソッドもオーバーライドする。
| |
− | <source lang="csharp">
| |
− | public class StudyTableViewSource : NSTableViewSource, IList<Study>
| |
− | {
| |
− | // 〜〜〜省略〜〜〜
| |
− |
| |
− | public override void SetObjectValue(NSTableView tableView, NSObject theObject, NSTableColumn tableColumn, int row)
| |
− | {
| |
− | var item = Items[row];
| |
− | var type = typeof(Study);
| |
− | var prop = type.GetProperty(tableColumn.Identifier, BindingFlags.Public | BindingFlags.Instance);
| |
− | if (prop == null)
| |
− | {
| |
− | return;
| |
− | }
| |
− | prop.SetValue(item, theObject.ToString());
| |
− | }
| |
− | }
| |
− | </source>
| |
− |
| |
− | ===セルのデザインを変える===
| |
− | セルのデザインをいじくるにはデータソースの以下のメソッドをオーバーライドしてその中でいじくりまわす。
| |
− | セルは初期状態でDrawsBackgroundプロパティがfalseに設定されており背景描画が無効化されているようなので、trueに設定したのちに各種操作をしている。
| |
− | <source lang="csharp">
| |
− | public class StudyTableViewSource : NSTableViewSource, IList<Study>
| |
− | {
| |
− | // 〜〜〜省略〜〜〜
| |
− |
| |
− | public override void WillDisplayCell(NSTableView tableView, NSObject cell, NSTableColumn tableColumn, int row)
| |
− | {
| |
− | // 編集不可カラムの背景色を少し暗くしてみる
| |
− | if (tableColumn.Editable == false)
| |
− | {
| |
− | if (cell is NSTextFieldCell)
| |
− | {
| |
− | var textfield = cell as NSTextFieldCell;
| |
− | textfield.DrawsBackground = true;
| |
− | textfield.BackgroundColor = NSColor.FromSrgb(0.9f, 0.9f, 0.9f, 1.0f);
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
| </source> | | </source> |
| | | |