使用NodeView + NodeStore显示分层数据

时间:2013-08-14 10:59:14

标签: c# mono gtk#

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

Father Mother
====== ======
Jon    Ann
 +Sons
 +--Jon  20
 +--Dave 10
 +Daughters
 +--Ann  
Ron    Mary
Paul   Eve
 +Sons
 +--Bob  4
如果他们是空的,不应该显示“儿子”和“女儿”。 我创建了三个商务类:父母,儿子和女儿,我正在创建TreeNode子类来显示它们。 我使用Monodevelop设计器设计了一个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 ();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

Gtk模型绑定与其他工具包完全不同。话虽这么说,这是你需要知道的开始:

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

  • NodeView(最简单)
  • 的TreeView

现在,AFAIC,NodeView只存在于GTK#中,即.Net绑定。 TreeView在所有其他绑定中都可用,并且是GTK + Core的一部分。不同的是,NodeView更容易使用但更有限。

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

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

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

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

  • NodeStore
  • ListStore
  • TreeStore

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

this链接中,我提到的每个案例的样本都可以尝试。我认为您应该使用“树”模型来完成您想要的而不是“节点”。

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