0

我想要一个 NodeView 来显示一些分层数据,如下所示:

Father Mother
====== ======
Jon    Ann
 +Sons
 +--Jon  20
 +--Dave 10
 +Daughters
 +--Ann  
Ron    Mary
Paul   Eve
 +Sons
 +--Bob  4

如果“儿子”和“女儿”为空,则不应显示它们。我创建了三个业务类:Parents、Son 和 Daughter,并且我正在创建 TreeNode 子类来显示它们。我用 Monodevelop 设计器设计了一个窗口,并用代码重新创建了 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 ();
        }
    }
}
4

1 回答 1

1

Gtk 模型绑定的工作方式与其他工具包完全不同。话虽如此,对于初学者来说,这是您需要了解的内容:

在 GTK 中调用了几种类型的“控件”或小部件,它们可以显示矩阵/列表数据:

  • 节点视图(最简单)
  • 树视图

现在,AFAIC,NodeView 仅存在于 GTK# 中,即 .Net 绑定。TreeView 在所有其他绑定中都可用,并且是 GTK+ 核心的一部分。不同之处在于,不知何故,NodeView 更易于使用但更有限。

如果您只需要显示列表数据,即没有分层数据(尽管您似乎需要),您将希望使用 NodeView

如果您需要显示分层数据,那么您将使用 TreeView。

无论您使用哪个,您还必须在该小部件中设置您需要显示的内容,例如您的列。GTK 中的 NodeView/TreeView 单元格和其他基本工具包之间的区别在于,例如,NodeView 列可以在其单元格内显示其他小部件,而不仅仅是文本,因此您可以拥有一个具有显示进度条的单元格的列,或者一个复选框。您在这些单元格中使用的小部件称为 CellRenderers,有 CellRendererText、CellRenderToggle 等。

现在,这些控件通过“商店”“绑定”到数据,例如:

  • 节点存储
  • 列表存储
  • 树店

您将使用哪一个取决于您的需求和您要使用的小部件类型,因此如果您只需要显示简单数据使用 NodeStore,如果您需要显示分层数据使用 TreeStore。这些数据存储的一个强大之处在于,您不仅可以在其中存储显示在 NodeView/TreeView 小部件上的数据,还可以存储任何其他不一定需要显示的数据,您甚至可以存储对象,例如,您可以有一个包含 4 列的商店,其中 3 列显示在小部件上,第四列保留完整对象的实例。

链接中,我提到的每种情况都有示例,您可以尝试。我认为你应该使用“树”模型来完成你想要的,而不是“节点”。

GTK 是一个强大的工具包,但有时很难理解它是如何工作的。我希望这个介绍对你有用。

于 2013-08-17T10:41:35.197 回答