我正在将TreeView与ListStore用作模型。当用户单击一行时,我想采取一些措施,但不使用单元格中的值,而是使用我从中创建该行的数据。
目前,我有TreeView,TreeModel(ListStore)和我自己的数据(我讽刺地称为模型)。
因此,问题是:
拥有模型是“正确”的吗?是我要显示的数据的对象表示形式,并用该数据填充ListStore以便在TreeView中显示,还是实现自己的TreeModel版本(包装我的数据,模型)以显示数据?
并且:
如果有人双击某行,我可以得到RowActivated事件(使用C#/Gtk#),该事件提供了到已激活行的路径。有了它,我可以得到一个TreeIter,然后得到一个单元格的值。但是,最好的方法是首先找到从其构造行的数据对象?\
(以某种方式,这个问题使我进入了第一个问题-通过思考,如果我尝试实现自己的TreeModel,将使数据对象更加容易...)
最佳答案
实现TreeModel非常麻烦/困难,因此大多数人只是将数据从其“实际”模型同步到TreeStore或ListStore中。
存储中的列不必以任何方式匹配 View 中的列。例如,您可以有一个包含您的实际托管数据对象的列。
将Cellrenderer添加到TreeView(可视)列时,可以在其属性和商店的列之间添加映射。例如,您可以将一个存储列映射到文本cellrenderer的字体,而将另一个存储列映射到同一cellrenderer的text属性。每次使用cellrenderer渲染特定的单元格时,都将使用映射从存储中检索值并将其应用于渲染器渲染之前的属性。
这是一个映射示例:
treeView.AppendColumn ("Title", renderer, "text", 0, "editable", 4);
这会将存储列0映射到渲染器的
text
GTK属性,并将存储列4映射到editable
属性。对于GTK属性名称,您可以检查GTK docs。请注意,上面的示例使用了一种便捷方法,该方法添加一列,向其添加渲染器,并通过params添加任意数量的映射。要将映射直接添加到一列(例如,具有多个渲染器的列)中,请将渲染器打包到该列中,然后使用TreeViewColumn.AddAttribute
或TreeViewColumn.SetAttributes
。您还可以设置将使用自定义数据功能代替映射。给定一个TreeIter和商店,这使您可以直接设置渲染器的属性-因此,如果要显示的所有数据都是从真实数据对象中琐碎地派生的,那么您甚至可以使商店仅包含一个单独的列。这些对象,并对所有 View 列使用数据功能。
这是一个数据函数的示例,其功能与上述映射示例完全相同:
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对象的属性,而且使您能够实现更复杂的显示逻辑-例如,仅在实际渲染单元格时才延迟处理派生值。
关于mono - 如何正确使用GtkTreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4511218/