GTK#中的自定义树状单元格渲染器 - 如何获取单元格数据?

时间:2011-11-25 20:57:59

标签: c# gtk# gtktreeview

我在GTK#中使用TreeView,现在我需要使用自定义单元格渲染器。

虽然几乎所有东西都可以使用,但是有一个缺失的部分:单元格渲染器必须知道要渲染的内容。

要渲染的数据是自定义类。我想从该类中检索一个字段。

这是我到目前为止所拥有的

public class TreeItemCellRenderer : CellRenderer
{
    public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
    {
        base.GetSize (widget, ref cell_area, out x_offset, out y_offset, out width, out height);

        height = 16;
    }

    protected override void Render (Gdk.Drawable window,
        Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
    {
        base.Render (window, widget, background_area, cell_area, expose_area, flags);

        using (var layout = new Pango.Layout(widget.PangoContext)) {
            layout.Alignment = Pango.Alignment.Left;
            layout.SetText("Hello, World!");

            StateType state = flags.HasFlag(CellRendererState.Selected) ?
                widget.IsFocus ? StateType.Selected : StateType.Active : StateType.Normal;

            window.DrawLayout(widget.Style.TextGC(state), cell_area.X, cell_area.Y, layout);
        }
    }
}

现在我想绘制我的自定义字段而不是“Hello,World!”。 一些谷歌搜索建议SetProperty / GetProperty是我需要的,但是:

var col = new TreeViewColumn("TreeItem", renderer);
col.AddAttribute(renderer, "tree-item", 0);

由于TreeItemCellRenderer没有名为“tree-item”的属性,因此在运行时引发错误。 此外,值得注意的是SetProperty 虚拟。

那我该怎么做呢?

3 个答案:

答案 0 :(得分:3)

实际上,唯一的问题是在自定义单元格渲染器中定义要渲染的值/数据不是在渲染器本身中完成的,而是在侦听器方法中完成的。

在您定义TreeView及其列和CellRenderers的窗口小部件类中,您还可以定义一个TreeCellDataFunc,它只是在呈现单元格之前调用的侦听器函数的一个邪恶隐藏名称。但它的名字已经有了#34; Data"内部,这就是你在该功能中应该做的事情:提供要渲染的数据。

TreeItemCellRenderer cellRenderer = new TreeItemCellRenderer();
column.SetCellDataFunc(cellRenderer, new Gtk.TreeCellDataFunc(AwesomeDataFunction));

/**
* Supplies the TreeItemCellRenderer with data for the current cell.
* */
private void AwesomeDataFunction(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
{
    (cell as TreeItemCellRenderer).<some self-declared property> = <any fitting value>;
}

您可能希望使用iter和model来获取所需的数据。在该函数之后调用CellRenderer的实际Render()函数。

总而言之,我认为整个TreeView / CellRenderer模型都是一团糟。虽然它确实有效并且您可以用它做大部分事情,但是完全不清楚您应该做些什么来实现您的目标。那个TreeView教程没问题,但实际上只显示了冰山一角。为什么没有用于细胞渲染的小部件超出我的范围。这会容易得多。

答案 1 :(得分:1)

您只需声明一个属性并在此示例中使用它。

class CellRendererSimple : CellRenderer
{

//property asigned to by treeviewcolumn
//eg. TreeViewColumn tvc = new TreeViewColumn("Column 0", new CellRendererSimple(),"tree_item",0);
[GLib.Property("tree_item")] //this line seems to be nessasary for the property to be recognised by the treeviewcolumn.
    public string tree_item
    {
        get;
        set;
    }

    protected override void Render(Gdk.Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
    {
        //this seems to be the minimum to render text
        GC gc = widget.Style.TextGC(StateType.Normal);
        Pango.Layout layout = new Pango.Layout(widget.PangoContext);
        layout.SetText(tree_item);//add the text to thelayout.
        //this is the actuall rendering
        window.DrawLayout(gc, expose_area.X, expose_area.Y, layout);
    }
}

答案 2 :(得分:0)

我没有找到一个真正的好答案,但我找到了一个解决方法。

我的目标始终是在保持指向拥有该值的类的“指针”的同时显示信息。 所以这就是我所做的:

  1. 仅声明一列(“标签”)
  2. 追加行,每行包含两个列 - 要显示的标签和类实例。这样就显示了第一行,但第二行是隐藏的
  3. 现在,获取每行的第二列将为我提供我想要的值,没有必须处理自定义渲染器并且没有随机数据出现在树中。

    我知道这不能回答这个问题,但它确实解决了我的特殊问题。如果其他人在此页面中结束,我希望此信息仍然有用。但如果您确实找到了更好的解决方案,请随时发布。