6

我似乎无法弄清楚如何创建一个具有 2 列的简单 NSOutlineView,以及一个深度超过 1 级的数据结构(层次结构)。

我已经研究了好几天了,我能找到的只是Objective C示例,我真的不能用于任何事情。

我知道这样做有不同的模式,一种是 DataSource 模式。我尝试创建一个继承自 NSOutlineViewDataSource 的类,但这就是我所得到的,我不知道接下来应该做什么!

假设我想在我的 NSOutlineView 中显示以下类:

public class Person
{
    public string Name {get;set;} // First column
    public int Age {get;set} // Second column
    public List<Person> Children {get;set} // Children
}

实现这一目标最简单的方法是什么?

4

2 回答 2

14

振作起来……MonoMac 中与级别无关的 NSOutlineView!

经过数百次谷歌搜索,并查看了 ObjC 和 C# 代码,我终于想出了如何去做!我会在这里发布我的解决方案,以防其他人需要它。

这可能是也可能不是最好的方法,但它对我有用。


第 1 步:在 Interface Builder 中,添加一个 NSOutlineView。向其中添加 2 列,并将它们的 Identifier 设置为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 新人的困扰。

于 2012-09-20T17:32:37.353 回答
2

我花了一点时间来追踪这个,但Xamarin 有一个如何做到这一点的例子这里

于 2014-01-14T01:44:26.427 回答