使NSTableView的行为类似于WPF StackPanel

时间:2012-12-19 21:38:23

标签: cocoa nstableview stackpanel monomac

我正在尝试在我的MonoMac项目中实现垂直StackPanel等效项,但我很难搞清楚它。我没有使用界面构建器,而是以编程方式创建控件(这是一个限制)。我尝试使用CollectionView,但该控件中的所有项目都在调整到相同的高度。

环顾互联网,似乎NSTableView是可行的方式,但我不知道该怎么做,特别是在使用MonoMac目标时使用C#。使用CollectionView允许我创建我想要渲染的视图,CollectionViewItem.ItemPrototype稍微简单一点。但是使用NSTableView,我似乎只能指定一个返回我想要显示的NSObject的数据源。如何获取这些数据,然后将它们绑定到我想要留在那里的视图?

我更喜欢C#代码,但我正处于接受任何和所有帮助的阶段!

1 个答案:

答案 0 :(得分:3)

我终于能够让它运转起来了。以下是一些想要试用它的人的代码。基本上,我们需要为所需的函数编写NSTableViewDelegate s。此实现也不会缓存控件或任何内容。 Cocoa API documentation提到使用标识符来重用控件或其他内容,但标识符字段在MonoMac中是get-only。

我最终在我的数据源本身中实现了我的NSTableViewDelegate函数,我相信它根本不是犹太教,但我不确定最佳做法是什么。

这是数据源类:

class MyTableViewDataSource : NSTableViewDataSource
{
    private NSObject[] _data;

    // I'm coming from an NSCollectionView, so my data is already in this format
    public MyTableViewDataSource(NSObject[] data)
    {
        _data = data;
    }

    public override int GetRowCount(NSTableView tableView)
    {
        return _data.Length;
    }

    #region NSTableViewDelegate Methods

    public NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, int row)
    {
        // MyViewClass extends NSView
        MyViewClass result = tableView.MakeView("MyView", this) as MyViewClass;
        if (result == null)
        { 
            result = new MyViewClass(_data[row]);
            result.Frame = new RectangleF(0, 0, tableView.Frame.Width, 100); // height doesn't matter since that is managed by GetRowHeight
            result.NeedsDisplay = true;
            // result.Identifier = "MyView"; // this line doesn't work because Identifier only has a getter
        }

        return result;
    }

    public float GetRowHeight(NSTableView tableView, int row)
    {
        float height = FigureOutHeightFromData(_data[row]); // run whatever algorithm you need to get the row's height
        return height;
    }

    #endregion
}

以下是以编程方式创建表格的代码段:

var tableView = new NSTableView();
var dataSource = new MyTableViewDataSource();

tableView.DataSource = dataSource;
tableView.HeaderView = null; // get rid of header row
tableView.GetViewForItem = dataSource.GetViewForItem;
tableView.GetRowHeight = dataSource.GetRowHeight;

AddSubView(tableView);

所以,它不是一个完美的StackPanel,因为需要手动计算行高,但它总比没有好。