使用NodeView+NodeStore来显示分层数据
本文关键字:分层 数据 显示 NodeView+NodeStore 使用 | 更新日期: 2023-09-27 18:27:49
我想要一个NodeView来显示一些分层数据,比如这样的:
Father Mother
====== ======
Jon Ann
+Sons
+--Jon 20
+--Dave 10
+Daughters
+--Ann
Ron Mary
Paul Eve
+Sons
+--Bob 4
如果"儿子"answers"女儿"是空的,就不应该显示。我已经创建了三个业务类:Parents、Son和Daughter,并且我正在创建TreeNode子类来显示它们。我用Monosdevelop设计器设计了一个Window,并用代码重新创建了nodeView。nodeview根本不显示任何内容,我想知道为什么。这是代码,在一个文件中,这样任何人都可以测试它:
using System;
using Gtk;
using System.Collections.Generic;
using System.Linq;
namespace Family.Model
{
public class Son {
public string Name {get;set;}
public string Age {get;set;}
public Son(string n,string a) {
Name=n;Age=a;
}
}
public class Parents
{
public string Father {get;set;}
public string Mother {get;set;}
public List<string> Daughters {get;set;}
public Dictionary<string,Son> Sons {get;set;}
public Parents() {
Daughters=new List<string>();
Sons=new Dictionary<string, Son>();
}
}
}
namespace Family.View
{
using Family.Model;
[TreeNode (ListOnly=false)]
public class ParentsNode:TreeNode
{
private Parents parents;
public ParentsNode (Parents p):base()
{
this.parents=p;
DaughtersRoot rootd=new DaughtersRoot();
SonsRoot roots=new SonsRoot();
if (p.Sons.Count>0) {
this.AddChild (roots);
p.Sons.Values.ToList ().ForEach (x=>roots.AddChild(new SonNode(x)));
}
if (p.Daughters.Count>0) {
this.AddChild (rootd);
p.Daughters.ForEach (x=>rootd.AddChild(new DaughterNode(x)));
}
OnChanged ();
}
[Gtk.TreeNodeValue(Column=0) ]
public string Father {
get { return parents.Father;}
set { parents.Father=value;OnChanged ();}
}
[Gtk.TreeNodeValue (Column=1)]
public string Mother {
get { return parents.Mother; }
set { parents.Mother=value;OnChanged ();}
}
}
[TreeNode(ListOnly=false)]
public class DaughtersRoot:TreeNode
{
[Gtk.TreeNodeValue(Column=0) ]
public string Label {
get {return "Daughters"; }
}
}
[TreeNode(ListOnly=false)]
public class SonsRoot:TreeNode
{
[Gtk.TreeNodeValue(Column=0) ]
public string Label {
get {return "Sons"; }
}
}
[TreeNode(ListOnly=false)]
public class DaughterNode:TreeNode {
private string mName;
public DaughterNode(string s):base() {
this.Name=s;
}
[Gtk.TreeNodeValue(Column=0) ]
public string Name {
get {return mName;}
set {mName=value;OnChanged ();}
}
}
[TreeNode(ListOnly=false)]
public class SonNode:TreeNode {
private Son son;
public SonNode(Son s):base() {
this.son=s;
OnChanged ();
}
[Gtk.TreeNodeValue(Column=0)]
public string Name {
get { return this.son.Name; }
set {son.Name=value;OnChanged ();}
}
[Gtk.TreeNodeValue(Column=1)]
public string Age {
get { return this.son.Age; }
set {son.Age=value;OnChanged ();}
}
}
public class MainWindow: Gtk.Window
{
private global::Gtk.ScrolledWindow GtkScrolledWindow;
private global::Gtk.NodeView treeFamily;
private NodeStore storeParents=new NodeStore(typeof(ParentsNode));
protected virtual void Build ()
{
global::Stetic.Gui.Initialize (this);
// Widget MainWindow
this.Name = "MainWindow";
this.Title = global::Mono.Unix.Catalog.GetString ("MainWindow");
this.WindowPosition = ((global::Gtk.WindowPosition)(4));
this.GtkScrolledWindow = new global::Gtk.ScrolledWindow ();
this.GtkScrolledWindow.Name = "GtkScrolledWindow";
this.GtkScrolledWindow.ShadowType = ((global::Gtk.ShadowType)(1));
this.treeFamily = new global::Gtk.NodeView ();
this.treeFamily.CanFocus = true;
this.treeFamily.Name = "treeFamily";
this.GtkScrolledWindow.Add (this.treeFamily);
this.Add (this.GtkScrolledWindow);
if ((this.Child != null)) {
this.Child.ShowAll ();
}
this.DefaultWidth = 400;
this.DefaultHeight = 300;
this.Show ();
this.DeleteEvent += new global::Gtk.DeleteEventHandler (this.OnDeleteEvent);
}
public MainWindow (): base (Gtk.WindowType.Toplevel) {
Build ();
Parents p=new Parents();
p.Father="Bob";
p.Mother="Mary";
storeParents.AddNode (new ParentsNode (p));
p=new Parents();
p.Father="Ron";
p.Mother="Ann";
p.Sons.Add ("David",new Son("David","20"));
p.Sons.Add ("Matt",new Son("Matt","10"));
p.Daughters.Add ("Elaine");
p.Daughters.Add ("Kate");
storeParents.AddNode (new ParentsNode(p));
this.treeFamily=new NodeView(storeParents);
Gtk.TreeViewColumn fatherColumn = new Gtk.TreeViewColumn
("Father",new CellRendererText(),"text",0);
Gtk.TreeViewColumn motherColumn = new Gtk.TreeViewColumn
("Mother",new CellRendererText(),"text",1);
treeFamily.AppendColumn (fatherColumn);
treeFamily.AppendColumn (motherColumn);
treeFamily.ShowAll ();
}
protected void OnDeleteEvent (object sender, DeleteEventArgs a) {
Application.Quit ();
a.RetVal = true;
}
}
class MainClass
{
public static void Main (string[] args) {
Application.Init ();
MainWindow win = new MainWindow ();
win.Show ();
Application.Run ();
}
}
}
GTK中有几种类型的"控件"或小部件可以显示矩阵/列表数据:
- NodeView(最简单)
- TreeView
现在,AFAIC,NodeView只存在于GTK#中,也就是.Net绑定中。TreeView在所有其他绑定中都可用,并且是GTK+核心的一部分。不同的是,NodeView在某种程度上更容易使用,但更有限。
如果您只需要显示列表数据,也就是说,不需要分层数据(尽管您似乎需要),那么您将希望使用NodeView
如果您需要显示分层数据,那么您将使用TreeView。
无论您使用哪种方式,您都必须在该小部件中设置您需要显示的内容,例如您的列。GTK中的NodeView/TreeView单元格与其他基本工具包的区别在于,例如,NodeView列可以在其单元格内显示其他小部件,而不仅仅是文本,因此您可以在一列中有一个显示进度条或复选框的单元格。在这些单元格中使用的小部件称为CellRenderers,有CellRendererText、CellRenderToggle等。
现在,这些控件通过"存储"与数据"绑定",例如:
- NodeStore
- ListStore
- TreeStore
您将再次使用哪一个取决于您的需求和将要使用的小部件类型,因此,如果您只需要显示简单数据,请使用NodeStore,如果您需要显示分层数据,则使用TreeStore。这些数据存储的一个强大之处在于,您不仅可以在其中存储NodeView/TreeView小部件上显示的数据,还可以存储任何其他不一定需要显示的数据。您甚至可以存储对象,例如,您可以有一个包含4列的存储,其中3列显示在小部件上,第四列保存完整对象的实例。
在这个链接中,有我提到的每个案例的样本,你可以试试。我认为你应该使用"树"模型来完成你想要的,而不是"节点"。
GTK是一个强大的工具包,但有时很难理解它是如何工作的。我希望这个介绍对你有用。