気を取り直して... MonoMac のレベルに依存しない NSOutlineView!
何百もの Google 検索を行い、ObjC と C# コードを調べた結果、ついにその方法を見つけました。他の誰かがそれを必要とする場合に備えて、ここに私の解決策を投稿します。
これが最善の方法である場合とそうでない場合がありますが、私にとってはうまくいきます。
ステップ 1 : Interface Builder で、NSOutlineView を追加します。それに 2 つの列を追加し、それらの識別子をcolName
、および に設定しcolAge
ます。
また、フォームにボタンを追加します。
ステップ 2 : NSOutlineView のアウトレットを作成します - 私lvMain
は VCL のバックグラウンドを持っているので、私に電話しました。また、ボタンのアクションを作成します (これは onClick ハンドラーになります)。
ステップ 3: XIB ファイルを保存し、Mono に戻ります。プロジェクト ファイルが更新されます。次に、ビューに使用するモデルを作成します。
この例では、単純な Person オブジェクトを使用します。
public class Person:NSObject
{
public string Name {
get;
set;
}
public int Age {
get;
set;
}
public List<Person> Children {
get;
set;
}
public Person (string name, int age)
{
Name = name;
Age = age;
Children = new List<Person>();
}
}
過度に複雑なことは何もありません。
ステップ 4:データソースを作成します。この例では、これは私が作ったものです:
public class MyDataSource:NSOutlineViewDataSource
{
/// The list of persons (top level)
public List<Person> Persons {
get;
set;
}
// Constructor
public MyDataSource()
{
// Create the Persons list
Persons = new List<Person>();
}
public override int GetChildrenCount (NSOutlineView outlineView, NSObject item)
{
// If the item is not null, return the child count of our item
if(item != null)
return (item as Person).Children.Count;
// Its null, that means its asking for our root element count.
return Persons.Count();
}
public override NSObject GetObjectValue (NSOutlineView outlineView, NSTableColumn forTableColumn, NSObject byItem)
{
// Is it null? (It really shouldnt be...)
if (byItem != null) {
// Jackpot, typecast to our Person object
var p = ((Person)byItem);
// Get the table column identifier
var ident = forTableColumn.Identifier.ToString();
// We return the appropriate information for each column
if (ident == "colName") {
return (NSString)p.Name;
}
if (ident == "colAge") {
return (NSString)p.Age.ToString();
}
}
// Oh well.. errors dont have to be THAT depressing..
return (NSString)"Not enough jQuery";
}
public override NSObject GetChild (NSOutlineView outlineView, int childIndex, NSObject ofItem)
{
// If the item is null, it's asking for a root element. I had serious trouble figuring this out...
if(ofItem == null)
return Persons[childIndex];
// Return the child its asking for.
return (NSObject)((ofItem as Person).Children[childIndex]);
}
public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
{
// Straight forward - it wants to know if its expandable.
if(item == null)
return false;
return (item as Person).Children.Count > 0;
}
}
ステップ 5 - 最良のステップ:データソースをバインドし、ダミー データを追加します。また、新しい要素を追加するたびにビューを更新したいと考えています。これはおそらく最適化される可能性がありますが、私はまだ「ああ、なんてこった」ゾーンにいるので、今のところ気にしません。
// Our Click Action
partial void btnClick (NSObject sender)
{
var p = new Person("John Doe",18);
p.Children.Add(new Person("Jane Doe",10));
var ds = lvMain.DataSource as MyDataSource;
ds.Persons.Add(p);
lvMain.ReloadData();
}
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
lvMain.DataSource = new MyDataSource();
}
この情報が、私のような MonoMac 初心者の悩みを抱えた魂の助けになれば幸いです。