「Xamarin.MacのNSTableViewでNSTableViewSourceを使う」の版間の差分
imported>Administrator 細 Administrator がページ「Xamarin.Mac/NSTableViewでNSTableViewSourceを使う」を「Xamarin.MacのNSTableViewでNSTableViewSourceを使う」に移動しました |
|||
| (4人の利用者による、間の10版が非表示) | |||
| 1行目: | 1行目: | ||
== | == 実装2:View Base == | ||
Xamarin. | [[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メソッドをオーバーライドすることで利用可能な状態となる。 | ||
| 77行目: | 138行目: | ||
* アウトレットは「_studyTableView」という名前にしておいた。 | * アウトレットは「_studyTableView」という名前にしておいた。 | ||
構造 | |||
*NSTableView → この例では、_studyTableViewインスタンス | *NSTableView → この例では、_studyTableViewインスタンス | ||
**NSTableColumn → この例では、これのIdentityと、Studyクラスのプロパティが一致したものに文字列を代入している | **NSTableColumn → この例では、これのIdentityと、Studyクラスのプロパティが一致したものに文字列を代入している | ||
| 101行目: | 163行目: | ||
なんと、この状態で実行するとテーブルの表示はされるが、クリックしても行選択ができない。 | なんと、この状態で実行するとテーブルの表示はされるが、クリックしても行選択ができない。 | ||
=== | ===行選択できるようにする=== | ||
これで良いのか知らんが以下で行選択が出来るようになった。 | これで良いのか知らんが以下で行選択が出来るようになった。 | ||
<source lang="csharp"> | <source lang="csharp"> | ||
| 117行目: | 179行目: | ||
</source> | </source> | ||
=== | ===セルを編集できるようにする=== | ||
Interface Builderを開き、各カラムに「Editable」のチェックを入れる(最初から入っていると思う)。 | Interface Builderを開き、各カラムに「Editable」のチェックを入れる(最初から入っていると思う)。 | ||
設定対象はカラムでありセルじゃないよ(Identity Inspectorを開くとクラスがNSTableColumnとなってるやつ)。 | 設定対象はカラムでありセルじゃないよ(Identity Inspectorを開くとクラスがNSTableColumnとなってるやつ)。 | ||
| 126行目: | 188行目: | ||
***NSTextFieldCell | ***NSTextFieldCell | ||
次にデータソースの以下のShouldEditTableColumnメソッドをオーバーライドし「true」を返すようにする。 | |||
前述のEditableのチェックをしておくことでこのメソッドが呼ばれるようになり、このメソッドでtrueを返すと実際に編集が可能な状態となるようだ。 | 前述のEditableのチェックをしておくことでこのメソッドが呼ばれるようになり、このメソッドでtrueを返すと実際に編集が可能な状態となるようだ。 | ||
<source lang="csharp"> | <source lang="csharp"> | ||
| 137行目: | 199行目: | ||
return true; | 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> | ||
2019年5月22日 (水) 05:12時点における最新版
実装2:View Base[編集 | ソースを編集]
Xamarin.MacにはNSTableViewSourceというNSTableViewを簡単に扱うための便利クラスがあるようだ。
列となるデータを準備する[編集 | ソースを編集]
まずはソースの元(テーブルの1行)となるクラスを用意する。
public class Study
{
public string Id { get; set; }
public string Name { get; set; }
}
行となるデータソースを準備する[編集 | ソースを編集]
次にデータソースを用意する。 NSTableViewSourceクラスを継承してGetRowCountメソッドとGetViewForItemメソッドをオーバーライドすることで利用可能な状態となる。 Cellベースでは「GetObjectValue」のところがViewベースでは「GetViewForItem」となっている。
この例ではNSTableColumnクラスのIdentifierプロパティの値と、前述のStudyクラスの各プロパティ名の簡易自動マッピングを行っている。NSTableColumnクラスのIdentifierプロパティはInterface Builderで設定した。
また、別途IList<>インターフェースを実装しておくとLINQで操作できたり色々便利だった。無くてもよい。
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;
}
}
あとはCellベースと同じ。
実装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」という名前にしておいた。
構造
- NSTableView → この例では、_studyTableViewインスタンス
- NSTableColumn → この例では、これのIdentityと、Studyクラスのプロパティが一致したものに文字列を代入している
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
- NSTableColumn ←これに「Editable」を設定する
次にデータソースの以下のShouldEditTableColumnメソッドをオーバーライドし「true」を返すようにする。 前述のEditableのチェックをしておくことでこのメソッドが呼ばれるようになり、このメソッドでtrueを返すと実際に編集が可能な状態となるようだ。
public class StudyTableViewSource : NSTableViewSource, IList<Study>
{
// 〜〜〜省略〜〜〜
public override bool ShouldEditTableColumn(NSTableView tableView, NSTableColumn tableColumn, int row)
{
return true;
}
}
上記のShouldEditTableColumnメソッドのみでは編集はできるが、編集終了後に値が反映されず、編集前の状態に戻ってしまう。 そこで以下のSetObjectValueメソッドもオーバーライドする。
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());
}
}
セルのデザインを変える[編集 | ソースを編集]
セルのデザインをいじくるにはデータソースの以下のメソッドをオーバーライドしてその中でいじくりまわす。 セルは初期状態でDrawsBackgroundプロパティがfalseに設定されており背景描画が無効化されているようなので、trueに設定したのちに各種操作をしている。
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);
}
}
}
}