メインメニューを開く

差分

Xamarin.MacのNSTableViewでNSTableViewSourceを使う

5,986 バイト追加, 2019年5月22日 (水) 05:12
==実装1実装2:View Base ==[[Xamarin.MacにはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。Mac]]にはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。
===列となるデータを準備する===
まずはソースの元(テーブルの1行)となるクラスを用意する。
<source lang="csharp">
</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メソッドをオーバーライドすることで利用可能な状態となる。
* Content Modeを「Cell Based」に設定し
* アウトレットは「_studyTableView」という名前にしておいた。
 
構造
*NSTableView → この例では、_studyTableViewインスタンス
**NSTableColumn → この例では、これのIdentityと、Studyクラスのプロパティが一致したものに文字列を代入している
 
<source lang="csharp">
public partial class MainWindowController : NSWindowController
なんと、この状態で実行するとテーブルの表示はされるが、クリックしても行選択ができない。
===行選択行選択できるようにする===
これで良いのか知らんが以下で行選択が出来るようになった。
<source lang="csharp">
};
}
</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>
匿名利用者