Cod*_*ous 17 listview lazy-loading gtk#
我想通过GTK#中的列表视图显示一个大型数据集,性能是一个问题.我目前正在使用支持ListStore的TreeView,但是将所有数据添加到ListStore需要永远.在GTK中是否有某种列表视图窗口小部件支持延迟加载数据?在Winforms中,您可以使用DataGridView的VirtualMode属性来处理这个问题,但是我没有看到任何类型的GTK.
据我所知,在Gtk中没有可以做你想做的小部件,但是,在最终结果中,你可以在TreeView中对VirtualMode属性做类似的事情.
TreeView控件的问题在于它会提前从模型中获取所有数据.如果它不是为了这个,那么我会建议一个模型唯一的方法解决这个问题,但不幸的是TreeView在获取数据时是贪婪的,因此需要控制从视图加载数据的时间,否则它将如何进行能够告诉行何时可见,从而通知模型,或代理在行变为可见时获取行的数据.
你需要3件事才能让它发挥作用
1)在树视图中使用的模型,该模型最初具有所有行,但在任何字段中都没有数据
2)从您使用的任何数据库中获取数据的方法
3)确定要获取数据的行的方法
前两项可以在模型级别完成.确定要获取的行需要Treeview小部件以及确定正在显示哪些行的方法.我在下面使用的方法不是最佳的,但它确实有效,并且可以根据您的用途进行整理和/或调整.
我使用代理类存储在模型中,用于获取特定于该行的数据.在我的例子中,它被称为ProxyClass.它获取并保存行的数据,该行最初为null.在这种情况下,Fetch方法只是创建并返回一个字符串"some data"+ id
这将保存在MyNode的实例中,该实例继承自TreeNode,表示一行数据.第一列返回代理中保存的数据,第二列(从未显示)保存代理类实例.
然后,您可以创建NodeStore,您的模型,使用MyNode(id)实例填充它,如下面的示例所示.
加载数据的控制是从CellDataFunc控制的.这种方法是实现这一目标的关键.CellDataFunc负责为CellRendererText中的文本设置由传递给它的迭代器标识的行中的特定列.每次树视图显示一行时,以及仅显示新显示的行时,都会调用它.因此,仅获取在显示器中呈现的单元格的数据.这为您提供了一种控制何时获取数据的方法,从而仅在您需要时才获取数据.
您可以使TreeView使用CellDataFunc根据需要加载数据,方法是将其应用于使用TreeViewColumn.SetCellDataFunc的其中一列.您只需要在一列上执行此操作,因为它可以获取整行的数据.
要通过检查当前单元格是否在可见范围内,可以停止除可见行之外的所有行都可以获取数据.要执行此操作,请调用TreeView.GetVisibleRange(out start,out end),然后查看传递给此函数的当前迭代器是否在开始和结束范围内,即TreePath对象,因此需要先将它们更改为TreeIters.Model.GetIter(out iter_start,start).然后检查是否iter.UserData.ToInt32()> = iter_start.UserData.ToInt32()并且小于iter_end.如果当前iter落在从iter_start到iter_end的范围内,则获取数据,否则保留它.
这是我的例子.
ProxyClass
namespace LazyTree
{
public class ProxyClass
{
int id;
string data;
public ProxyClass (int id)
{
this.id = id;
data = null;
}
public void Fetch()
{
data = "some data " + id;
}
public int Id
{
get { return id; }
}
public string Data
{
get {return data;}
}
}
}
Run Code Online (Sandbox Code Playgroud)
自定义TreeNode实例
namespace LazyTree
{
[Gtk.TreeNode (ListOnly=true)]
public class MyNode : Gtk.TreeNode
{
protected ProxyClass proxy;
public MyNode (int id)
{
proxy = new ProxyClass(id);
}
[Gtk.TreeNodeValue (Column=1)]
public ProxyClass Proxy
{
get {return proxy;}
}
[Gtk.TreeNodeValue (Column=0)]
public string Data
{
get { return proxy.Data; }
}
}
}
Run Code Online (Sandbox Code Playgroud)
包含滚动窗口和树视图的窗口.这也是定义CellDataFunc的地方,尽管可以放在任何地方.
namespace LazyTree
{
public class MyWindow : Gtk.Window
{
int NUMBER_COLUMNS = 10000;
Gtk.NodeStore store;
Gtk.NodeStore Store {
get {
if (store == null) {
store = new Gtk.NodeStore (typeof (MyNode));
for(int i = 0; i < NUMBER_COLUMNS; i++)
{
store.AddNode (new MyNode (i));
}
}
return store;
}
}
protected void CellDataFunc(Gtk.TreeViewColumn column,
Gtk.CellRenderer cell,
Gtk.TreeModel model,
Gtk.TreeIter iter)
{
try {
string data = (string)model.GetValue(iter, 0);
ProxyClass proxy = (ProxyClass)model.GetValue(iter, 1);
Gtk.TreeView view = (Gtk.TreeView)column.TreeView;
Gtk.TreePath start, end;
bool go = view.GetVisibleRange(out start,out end);
Gtk.TreeIter iter_start, iter_end;
if(go)
{
model.GetIter(out iter_start, start);
model.GetIter(out iter_end, end);
}
if (go &&
data == null &&
iter.UserData.ToInt32() >= iter_start.UserData.ToInt32() &&
iter.UserData.ToInt32() <= iter_end.UserData.ToInt32())
{
Console.WriteLine("Lazy Loading " + proxy.Id + ", Visible: " + cell.Visible);
proxy.Fetch();
}
((Gtk.CellRendererText)cell).Text = data;
} catch(Exception e) {
Console.WriteLine("error: " + e);
}
}
public MyWindow () : base("Lazy Tree")
{
Gtk.NodeView view = new Gtk.NodeView(Store);
Gtk.ScrolledWindow scroll = new Gtk.ScrolledWindow();
scroll.Add(view);
Add(scroll);
Gtk.CellRendererText cell = new Gtk.CellRendererText ();
view.AppendColumn ("Lazy Data", cell, "text", 0);
Gtk.TreeViewColumn column = view.GetColumn(0);
column.SetCellDataFunc(cell, CellDataFunc);
}
protected override bool OnDeleteEvent (Gdk.Event ev)
{
Gtk.Application.Quit ();
return true;
}
public static void Main()
{
Gtk.Application.Init ();
MyWindow win = new MyWindow();
win.SetDefaultSize(200, 200);
win.ShowAll ();
Gtk.Application.Run ();
}
}
}
Run Code Online (Sandbox Code Playgroud)
希望这是你的事后.
有关每种方法及其参数的详细说明,请参阅c文档.Mono文档留下了很多不足之处.
SetCellDataFunc(C docs) http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-cell-data-func
(CeCellDataFunc) http://developer.gnome.org/gtk/stable/GtkTreeViewColumn.html#GtkTreeCellDataFunc
(DestroyFunc) http://developer.gnome.org/glib/unstable/glib-Datasets.html#GDestroyNotify
| 归档时间: |
|
| 查看次数: |
2926 次 |
| 最近记录: |