我使用带有ListStore的TreeView作为模型。当用户点击一行时,我想采取一些行动但不使用单元格中的值,但使用我创建的行数据...
目前我有TreeView,TreeModel(ListStore)和我自己的数据(我讽刺地称之为模型)..
所以问题是:
拥有一个模型是否“正确” - 我想要显示的数据的对象表示,并用TreeView中的数据填充ListStore,或者更好地实现自己的TreeModel版本(包装)我的数据模型)来显示数据?
还有:
如果有人双击一行,我可以获得RowActivated事件(使用C#/ Gtk#),该事件提供激活行的路径。有了它我可以得到一个TreeIter并使用它我可以得到一个单元格的值。但是,首先要找到构造行的数据对象的最佳做法是什么? (不知何故,这个问题让我想到了第一个问题 - 如果我试图实现自己的TreeModel,那么通过思考会让数据对象变得更容易......)
答案 0 :(得分:7)
实现TreeModel非常笨拙/困难,因此大多数人只是将数据从“真实”模型同步到TreeStore或ListStore。
商店中的列不必以任何方式匹配视图中的列。例如,您可以拥有一个包含真实托管数据对象的列。
将cellrenderer添加到TreeView(可视)列时,可以在其属性和商店列之间添加映射。例如,您可以将一个商店列映射到文本cellrenderer的字体,将另一个商店列映射到同一个cellrenderer的text属性。每次使用cellrenderer渲染特定单元格时,映射将用于从商店中检索值,并在呈现之前将它们应用于渲染器的属性。
以下是映射示例:
treeView.AppendColumn ("Title", renderer, "text", 0, "editable", 4);
这将存储列0映射到渲染器的text
GTK属性,并将存储列4映射到editable
属性。对于GTK属性名称,您可以查看GTK docs。请注意,上面的示例使用了一种方便的方法,即添加列,向其添加渲染器并通过参数添加任意数量的映射。要直接向列添加映射(例如,包含多个渲染器的列),请将渲染器打包到列中,然后使用TreeViewColumn.AddAttribute
或TreeViewColumn.SetAttributes
。
您还可以设置将使用的自定义数据函数,而不是映射。这允许您在给定TreeIter和商店的情况下直接设置渲染器的属性 - 因此,如果您要显示的所有数据都是从您的实际数据对象中简单派生的,您甚至可以让您的商店只包含一列这些对象,并为所有视图列使用数据函数。
这是一个数据函数的例子,它完全符合上面的映射示例:
treeColumn.SetCellDataFunc (renderer, delegate (TreeViewColumn col,
CellRenderer cell, TreeModel model, TreeIter iter)
{
var textCell = (CellRendererText) cell;
textCell.Text = (string) model.GetValue (iter, 0);
textCell.Editable = (bool) model.GetValue (iter, 4);
});
显然,数据函数功能更强大,因为它们不仅可以使用更复杂的GTK对象的属性,还可以实现更复杂的显示逻辑 - 例如,只有在实际渲染单元格时,才会懒惰地处理派生值。 / p>