The TreeView widget is one of the more complex GTK widgets. It is well worth while spending some time studing it carefully.
These widgets are designed around a Model/View/Controller design and consists of four major parts:
GtkTreeView : the tree view widget
GtkTreeViewColumn : the view column
GtkCellRenderer : the cell renderers
GtkTreeModel : the model interface
A quick look at the situation boils down to this:
CellRender -----> TreeViewColumn -----> TreeView
A cell (CellRenderer) of type text, pixbuf or toggle is created and packed into a newly created column (TreeViewColumn). The column in turn is appended to the tree (TreeView). Data is now added to the tree model (TreeStore or ListStore) and the model is associated with the newly created tree.
Lets start with a simple example and explain as we go:
We'll create a simple list view with one column and text data stored in it. We could of course create multiple columns of different types but for our purposes, simple is better.
Lets create the TreeView widget first. We'll assume that the parent widget that we are going to pack the TreeView widget into has already been created.
First we create a ListStore for holding the data that our list widget is going to display.
The ListStore object is a list model for use with a TreeView widget. It implements the TreeModel interface, and consequentialy, can use all of the methods available there. It also implements the TreeSortable interface so it can be sorted by the view. Finally, it also implements the tree interface.
ListStore store = null;
Now we create a new TreeView widget and associate our newly created ListStore with the TreeView.
TreeView tv = new TreeView (store);
We could also have created a TreeView without the "store" and added it to the TreeModel after the fact, like so:
TreeView tv = new TreeView (); tv.Model = store;
We can now assign attributes to the TreeView such as making sure headers are visible, headers are clickable, enable search in columns, etc. Headers refer to the column headers that appear as buttons and may be tied to such functions as sorting the view of column data.
tv.HeadersVisible = true; tv.HeadersClickable = false; tv.EnableSearch = false;
Next we want to add columns to our TreeView. We are going to add one column. We get a new TreeViewColumn and a new CellRenderer of type text to add to our column.
TreeViewColumn attributes which are added with AddAttribute can be used to set such things as column colours.
TreeViewColumn NameCol = new TreeViewColumn (); CellRenderer NameRenderer = new CellRendererText (); NameCol.Title = "Name"; NameCol.PackStart (NameRenderer, true); NameCol.AddAttribute (NameRenderer, "text", 0); tv.AppendColumn (NameCol);
Since we aren't going to add any more columns to our TreeView we can finish by packing it into whatever parent widget we have.
mywidget.Add (tv); mywidget.ShowAll ();
Our next task is to to populate the TreeStore with data. Data is stored in the ListStore that was created as the first step above. When a ListStore or TreeStore is created we tell it what type of data the store is holding for each column . In the example below we have one column of type string.
store = new ListStore ((int)TypeFundamentals.TypeString);
If we had more than one column we would expand the creation of the ListStore to include those columns and their type. Here is an example that creates two columns, one of type boolean and one of type string.
store = new ListStore ((int)TypeFundamentals.TypeBoolean,(int)TypeFundamentals.TypeString);Right now lets put some data in our list. We need to get a new TreeIter. A TreeIter is used to store the location where the data will be stored. The TreeIter is updated automatically here bye a call to store.Append, we don't actually set the TreeIter. We will need to append the TreeIter to the "store" to before we can place data in it.
TreeIter iter = new TreeIter ();Great now lets put four rows of text data into the list. The ListStore and TreeStore actually store a Glib.Value not a text string so first we must store our string in a Glib.Value then we can set the value in the ListStore. Note the 0 in the SetValue call is actually the column we are writing data to.
for (int i = 0; i < 4; i++) { GLib.Value value = new Glib.Value(data +i.ToString()); store.Append (out iter); store.SetValue (iter, 0, value); }
Here is a example of what we have just done, complete with toplevel window.
namespace Samples { using System; using System.Drawing; using GLib; using Gtk; using GtkSharp; public class TreeView { public static void Main (string[] args) { TreeStore store = null; Application.Init (); store = new TreeStore ((int)TypeFundamentals.TypeString, (int)TypeFundamentals.TypeString); TreeIter iter = new TreeIter (); for (int i=0; i<10; i++) { GLib.Value Name = new GLib.Value ("Demo " + i.ToString()); GLib.Value Type = new GLib.Value ("Data " + i.ToString()); store.Append (out iter); store.SetValue (iter, 0, Name); store.SetValue (iter, 1, Type); } Window win = new Window ("TreeView List Demo"); win.DeleteEvent += new DeleteEventHandler (delete_cb); win.DefaultSize = new Size (400,250); ScrolledWindow sw = new ScrolledWindow (); win.Add (sw); TreeView tv = new TreeView (store); tv.HeadersVisible = true; TreeViewColumn DemoCol = new TreeViewColumn (); CellRenderer DemoRenderer = new CellRendererText (); DemoCol.Title = "Demo"; DemoCol.PackStart (DemoRenderer, true); DemoCol.AddAttribute (DemoRenderer, "text", 0); tv.AppendColumn (DemoCol); TreeViewColumn DataCol = new TreeViewColumn (); CellRenderer DataRenderer = new CellRendererText (); DataCol.Title = "Data"; DataCol.PackStart (DataRenderer, false); DataCol.AddAttribute (DataRenderer, "text", 1); tv.AppendColumn (DataCol); sw.Add (tv); sw.Show(); win.ShowAll (); Application.Run (); } private static void delete_cb (System.Object o, DeleteEventArgs args) { Application.Quit (); args.RetVal = true; } } }