[Gtk-sharp-list] Problems with TreeView

Daniel Morgan danielmorgan at verizon.net
Tue Aug 16 23:02:39 EDT 2005


I have an example of a TreeView using a ListStore tree model that is 
editable.  It can data bind to a data table.  It is not complete, but it 
can give you an idea of how to get your program working.

The thing is to move most of your logic into non-static fields and 
methods.  Use a constructor of your main class to initialize the gtk# 
stuff.  Make all your methods non-static except Main.

As for store, you had store declared locally in the Main function but 
you also had it as a field in the class.  store you had in Main was not 
the same store in Word_Edited.

class MainClass
{
	// Make the variable store visible to the whole class to use it
	// in the code for the Edited event
	ListStore store;

	MainClass() 
	{
		Window window = new Window ("TreeView");
		window.DeleteEvent += Window_Deleted;

		VBox vertBox = new VBox();
		vertBox.BorderWidth = 6;

		window.Add(vertBox);

		// Definition of my TreeView
		TreeView treeView = new TreeView();
		treeView.HeadersVisible = true;

		vertBox.Add(treeView);

		// Definition of the colums
		TreeViewColumn column = new TreeViewColumn();
		column.Title = "Word";
		CellRendererText colText = new CellRendererText();

		// Here i add the editable flag and the Edited event
		colText.Editable = true;
		colText.Edited += Word_Edited;
		column.PackStart (colText, true);
		column.AddAttribute (colText, "text", 0);
		treeView.AppendColumn (column);

		column = new TreeViewColumn();
		column.Title = "Page";
		colText = new CellRendererText();

		// Here i add the editable flag and the Edited event
		colText.Editable = true;
		colText.Edited += Word_Edited;
		column.PackStart (colText, true);
		column.AddAttribute (colText, "text", 1);
		treeView.AppendColumn (column);

		// Definition of the field types
		store = new ListStore (typeof (string), typeof(string));
		treeView.Model = store;

		// Putting stuff in the list
		TreeIter iterator = new TreeIter();
		iterator = store.AppendValues("ChangeMe", "1");

		// Show the not working stuff :-/
		window.ShowAll();
	}

	// My not working code, when a field is edited
	void Word_Edited (object o, EditedArgs e)
	{
		// When edited get me the current field
		TreeIter iterator;
		TreePath path = new TreePath(e.Path);

		// Try to write the new entry to the field and start
		// to crash awfully when using static
		store.GetIter(out iterator, path);
		store.SetValue(iterator, 0, e.NewText);
	}


	void Window_Deleted (object o, DeleteEventArgs e)
	{
		Application.Quit();
	}
	
	public static void Main(string [] args)
	{
		Application.Init();
		MainClass mc = new MainClass();
		Application.Run();		
	}
}


André Kuntze wrote:

>Hi everybody,
>
>i am trying to do the following in mono using c# and gtk#: Having a
>simple two column list with word and numbers. When you edit one field in
>any column, write the new text into the edited field.
>
>This must sound so newbish but i am struggeling with this a few hours
>now and so i decided to ask some people in the know. Til now i got this:
>
>** SNIP: CODE STARTS HERE
>
>
>/*
>*	Filename:	TreeViewTryOut.cs
>*	Date:		15.08.2005
>*
>*	Description:	This program is a TryOut for the editable
>*			TreeView - widget.
>*			The rows in the TreeView are editable and should
>*			take the new value, when entered.
>*/
>
>using System;
>using Gtk;
>
>class MainClass{
>	
>	// Make the variable store visible to the whole class to use it
>	// in the code for the Edited event
>	ListStore store;
>	
>	public static void Main(string [] args){
>		Application.Init();
>
>		// Definition of my window, which contains the editable
>		// Two - Column - List
>		Window window = new Window ("TreeView");
>		window.DeleteEvent += Window_Deleted;
>
>		VBox vertBox = new VBox();
>		vertBox.BorderWidth = 6;
>
>		window.Add(vertBox);
>
>
>		// Definition of my TreeView
>		TreeView treeView = new TreeView();
>		treeView.HeadersVisible = true;
>
>		vertBox.Add(treeView);
>
>
>		// Definition of the colums
>		TreeViewColumn column = new TreeViewColumn();
>		column.Title = "Word";
>		CellRendererText colText = new CellRendererText();
>
>		// Here i add the editable flag and the Edited event
>		colText.Editable = true;
>		colText.Edited += Word_Edited;
>		column.PackStart (colText, true);
>		column.AddAttribute (colText, "text", 0);
>		treeView.AppendColumn (column);
>
>		column = new TreeViewColumn();
>		column.Title = "Page";
>		colText = new CellRendererText();
>
>		// Here i add the editable flag and the Edited event
>		colText.Editable = true;
>		colText.Edited += Word_Edited;
>		column.PackStart (colText, true);
>		column.AddAttribute (colText, "text", 1);
>		treeView.AppendColumn (column);
>
>
>		// Definition of the field types
>		ListStore store = new ListStore (typeof (string), typeof
>			(string));
>		treeView.Model = store;
>
>
>		// Putting stuff in the list
>		TreeIter iterator = new TreeIter();
>		iterator = store.AppendValues("ChangeMe", "1");
>
>
>		// Show the not working stuff :-/
>		window.ShowAll();
>		Application.Run();
>	}
>
>
>	// My not working code, when a field is edited
>	static void Word_Edited (object o, EditedArgs e){
>		// When edited get me the current field
>		TreeIter iterator;
>		TreePath path = new TreePath(e.Path);
>
>		// Try to write the new entry to the field and start
>		// to crash awfully when using static
>		store.GetIter(out iterator, path);
>		store.SetValue(iterator, 0, e.NewText);
>	}
>
>
>	static void Window_Deleted (object o, DeleteEventArgs e){
>		Application.Quit();
>	}
>}
>
>** SNIP: CODE ENDS HERE
>
>
>
>which gives me a crying compiler like this:
>
>** SNIP: STARTS CRYING HERE
>
>andre at gremLin:~/programming/mono/IndexTool$ mcs -pkg:gtk-sharp
>TreeViewTryOut.csTreeViewTryOut.cs(27) error CS0103: The name `v' could
>not be found in `MainClass'
>TreeViewTryOut.cs(67) warning CS0219: The variable 'iterator' is
>assigned but its value is never used
>TreeViewTryOut.cs(84) error CS0120: An object reference is required for
>the non-static field `store'
>TreeViewTryOut.cs(85) error CS0120: An object reference is required for
>the non-static field `store'
>TreeViewTryOut.cs(15) warning CS0169: The private field
>'MainClass.store' is never used
>Compilation failed: 3 error(s), 2 warnings
>
>** SNIP: STOPS CRYING HERE
>
>
>I think the problem so far is, that my store variable is used in Main
>which is static. But when i make store static and edit some entry the
>program crashes hard like:
>
>
>** SNIP: BAD CRASH STARTS HERE
>
>andre at gremLin:~/programming/mono/IndexTool$ mono TreeViewTryOut.exe
>
>Unhandled Exception: System.Reflection.TargetInvocationException:
>Exception has been thrown by the target of an invocation. --->
>System.NullReferenceException: Object reference not set to an instance
>of an object
>in <0x0004d> MainClass:Word_Edited (System.Object o, Gtk.EditedArgs e)
>in <0x00000> <unknown method>
>in (wrapper managed-to-native)
>System.Reflection.MonoMethod:InternalInvoke (object,object[])
>in <0x0006f> System.Reflection.MonoMethod:Invoke (System.Object obj,
>BindingFlags invokeAttr, System.Reflection.Binder binder,
>System.Object[] parameters, System.Globalization.CultureInfo culture)---
>End of inner exception stack trace ---
>
>in <0x00104> System.Reflection.MonoMethod:Invoke (System.Object obj,
>BindingFlags invokeAttr, System.Reflection.Binder binder,
>System.Object[] parameters, System.Globalization.CultureInfo culture)
>in <0x00017> System.Reflection.MethodBase:Invoke (System.Object obj,
>System.Object[] parameters)
>in <0x000b3> System.Delegate:DynamicInvokeImpl (System.Object[] args)
>in <0x00028> System.MulticastDelegate:DynamicInvokeImpl (System.Object[]
>args)
>in <0x0000e> System.Delegate:DynamicInvoke (System.Object[] args)
>in <0x00147>
>GtkSharp.voidObjectstringstringSignal:voidObjectstringstringCallback
>(IntPtr arg0, System.String arg1, System.String arg2, Int32 key)
>in (wrapper native-to-managed)
>GtkSharp.voidObjectstringstringSignal:voidObjectstringstringCallback
>(intptr,intptr,intptr,int)
>in <0x00000> <unknown method>
>in (wrapper managed-to-native) Gtk.Application:gtk_main ()
>in <0x00007> Gtk.Application:Run ()
>in <0x00370> MainClass:Main (System.String[] args)
>
>** SNIP: BAD CRASH ENDS HERE
>
>
>Any ideas? I am justing starting with mono and gtk# and so far i like it
>a lot but i have so much to learn before stopping to ask newbie
>questions :-/
>
>I hope this big post is somehow easy to read. I edited a bit in
>evolution so it was more readable for me. Hope that didn't kill the
>formating information.
>  
>

-------------- next part --------------
// $ mcs /out:TestDataGrid.exe TestDataGrid.cs DataGrid.cs -pkg:gtk-sharp-2.0 /r:System.Data.dll
// TestDataGrid.cs
namespace Mono.Data.GtkSharp 
{
	using System;
	using System.Collections;
	using System.Collections.Specialized;
	using System.Configuration;
	using System.Data;
	using System.Data.Common;
	using System.Data.SqlTypes;
	using System.Text;
	using System.IO;
	using System.Reflection;
	using System.Runtime.Remoting;
	using System.Runtime.InteropServices;
	using System.Diagnostics;

	using Gdk;
	using Gtk;

	public class TestDataGrid 
	{
		private DataTable table;
		private Gtk.Window win;
		private DataGrid grid;
		//private TextView textView;

		public static readonly string ApplicationName = "Gtk# DataGrid Test";	

		public TestDataGrid () 
		{
			CreateGui ();
		}

		public DataGrid Grid {
			get {
				return grid;
			}
		}

		public void Show () 
		{
			win.ShowAll ();
		}

		public void CreateGui () 
		{
			win = new Gtk.Window (ApplicationName);
			win.DeleteEvent += new Gtk.DeleteEventHandler (OnWindow_Delete);
			win.BorderWidth = 4;
			win.SetDefaultSize (600, 500);
			
			VBox vbox = new VBox (false, 4);
			win.Add (vbox);

			MenuBar mb = CreateMenuBar ();
			vbox.PackStart (mb, false, false, 0);
			
			VPaned vpaned = new VPaned ();
			vbox.PackStart (vpaned, true, true, 0);
			grid = CreateOutputResultsDataGrid();
			vpaned.Add1 (grid);
		}

		DataGrid CreateOutputResultsDataGrid () 
		{
			DataGrid grid = new DataGrid ();

			//grid.View.ButtonReleaseEvent +=
			//	new Gtk.ButtonReleaseEventHandler (OnDataGridButtonRelease);
			//grid.Editable = false;

			return grid;
		}

		void OnWindow_Delete (object o, Gtk.DeleteEventArgs args) 
		{
			QuitApplication();
		}

		void QuitApplication () 
		{
			Application.Quit ();
		}

		public static void DoEvents () 
		{
			while (Application.EventsPending ()) 
				Application.RunIteration ();
		}

		public DataTable BuildDataTableSample() 
		{
			table = new DataTable();

			int maxColumns = 5;
			int maxRows = 3;

			for(int i = 0; i < maxColumns; i++) {
				string columnName = String.Format("Column{0}", i);
				table.Columns.Add(columnName);
			}
			
			for(int r = 0; r < maxRows; r++) {
				DataRow row = table.NewRow();
				for(int c = 0; c < table.Columns.Count; c++) {
					string cellValue = String.Format("(Row{0},Column{1})", r, c);
					row[c] = cellValue;
				}
				table.Rows.Add(row);
			}

			return table;
		}

		void OnMenu_DumpTable (object o, EventArgs args) 
		{
			Console.Error.WriteLine("__===========  T a b l e     D u m p  =========__");
			Console.Error.WriteLine("Row Count: " + table.Rows.Count.ToString());
			for(int r = 0; r < table.Rows.Count; r++) {
				DataRow row = table.Rows[r];
				StringBuilder sb = new StringBuilder();
				for(int c = 0; c < table.Columns.Count; c++) {
					string s = row[c].ToString();
					sb.Append(s);
					sb.Append(" ");
				}
				Console.Error.WriteLine(sb.ToString());
			}
			Console.Error.WriteLine("=-----------------------------------------------=");
		}

		void OnMenu_Editable (object o, EventArgs args) 
		{
			grid.Editable = !grid.Editable;
		}

		void OnMenu_AddNew (object o, EventArgs args) 
		{
			AddNew();
		}

		void OnMenu_DeleteSelectedRow (object o, EventArgs args) 
		{
			int selectedRow = 0;
			selectedRow = grid.SelectedRow;
			if (selectedRow >= 0)
				grid.DeleteRow (selectedRow);
		}

		void AddNew() 
		{
			grid.AddNew();
		}

		public MenuBar CreateMenuBar () {
			MenuBar menuBar = new MenuBar ();
			Menu menu;
			MenuItem item;
			MenuItem barItem;

			menu = new Menu ();

			item = new MenuItem ("Add Row");
			item.Activated += new EventHandler (OnMenu_AddNew);
			menu.Append (item);

			item = new MenuItem ("Dump Table");
			item.Activated += new EventHandler (OnMenu_DumpTable);
			menu.Append (item);

			item = new MenuItem ("Editable");
			item.Activated += new EventHandler (OnMenu_Editable);
			menu.Append (item);

			item = new MenuItem ("Delete Selected Row");
			item.Activated += new EventHandler (OnMenu_DeleteSelectedRow);
			menu.Append (item);

			barItem = new MenuItem ("Test");
			barItem.Submenu = menu;
			menuBar.Append (barItem);

			return menuBar;
		}

		public static int Main (string[] args) 
		{
			Application.Init ();
			TestDataGrid test = new TestDataGrid ();
			DataTable sampleTable = test.BuildDataTableSample();
			test.Grid.DataSource = sampleTable;
			test.Grid.DataBind();
			test.Show ();
			DoEvents ();
			//test.Grid.Editable = false;
			Application.Run ();
			return 0;
		}
	}
}

-------------- next part --------------
// DataGrid.cs
namespace Mono.Data.GtkSharp
{
	// notice System.Data is not references here

	using System;
	using System.Collections;
	using System.ComponentModel;
	using System.Reflection;
	using System.Runtime.InteropServices;
	using System.Text;
	
	using GLib;
	using Gtk;

	public class DataGridColumn 
	{
		private string columnName = "";
		private TreeViewColumn treeViewColumn = null;
		public CellRendererText Renderer = null; // should be internal

		public string ColumnName {
			get {
				return columnName;
			}
			set {
				columnName = value;
			}
		}

		public TreeViewColumn TreeViewColumn {
			get {
				return treeViewColumn;
			}
			set {
				treeViewColumn = value;
			}
		}
	}

	public class DataGrid : VBox {
		private ListStore store;
		private TreeView treeView;

		public ArrayList gridColumns; // TODO: make Columns a collection

		public DataGrid () : base(false, 4) {		
			ScrolledWindow sw = new ScrolledWindow ();
			this.PackStart (sw, true, true, 0);

			treeView = new TreeView (store);
			treeView.HeadersVisible = true;
			//treeView.ModifyFont (Pango.FontDescription.FromString ("courier new"));

			gridColumns = new ArrayList(0);

			sw.Add (treeView);

			store = new ListStore (GLib.GType.String);

			treeView.EnableSearch = true;
			treeView.HeadersClickable = true;
			dataMember = "";
			dataSource = null;
			
			
		}

		ArrayList bindrows = null;
		object resolvedDataSource = null;

		private bool editable = true;

		private object dataSource;

		private string dataMember;

		public int SelectedRow { 
			get {
				TreeIter iter;
				TreeModel model;
				TreeSelection selection = treeView.Selection;
				if (selection.GetSelected (out model, out iter)) {
					TreePath[] path = selection.GetSelectedRows (out model);
					return path[0].Indices[0]; // return selected row 
				}
				else
					return -1; // not selected
			}
		}

		public TreeIter SelectedIter {
			get {
				TreeIter iter;
				TreeModel model;
				TreeSelection selection = treeView.Selection;
				if (selection.GetSelected (out model, out iter))
					return iter; // return seelcted iter
				else
					return TreeIter.Zero; // not selected
			}

		}

		public TreeView View 
		{
			get 
			{
				return treeView;
			}
		}

		public object DataSource 
		{
			get 
			{
				return dataSource;
			}
			set 
			{
				dataSource = value;
			}
		}

		public string DataMember 
		{
			get 
			{
				return dataMember;
			}
			set 
			{
				dataMember = value;
			}
		}

		public ListStore Store 
		{
			get 
			{
				return store;
			}
		}

		public ArrayList Columns 
		{
			get 
			{
				return gridColumns;
			}
		}

		public bool Editable {
			get {
				return editable; // not a good way to see if its editable or not 
				// because various columns could be editable and others non-editable
			}

			set {
				editable = value;
				if (value == true) {
					for(int c = 0; c < gridColumns.Count; c++) {
						DataGridColumn col = (DataGridColumn) gridColumns[c];
						col.TreeViewColumn.Clickable = true;
						col.Renderer.Mode = CellRendererMode.Editable;
						col.Renderer.Editable = true;
					}
					treeView.RulesHint = true;
					treeView.Selection.Mode = SelectionMode.Single;
				}
				else {
					for(int c = 0; c < gridColumns.Count; c++) {
						DataGridColumn col = (DataGridColumn) gridColumns[c];
						col.TreeViewColumn.Clickable = false;
						col.Renderer.Mode = CellRendererMode.Inert;
						col.Renderer.Editable = false;
					}
					treeView.RulesHint = false;
					treeView.Selection.Mode = SelectionMode.Single;
				}
			}
		}

		public int AddNew() 
		{
			// TODO: need to check if resolved data source is not null

			IBindingList b = (IBindingList) resolvedDataSource;

			if (b.AllowNew) {
				object obj = b.AddNew();
				if (obj == null) {
					//Console.Error.WriteLine("obj is null");
				}
				else {
					//Console.Error.WriteLine("Type: " + obj.GetType().ToString());
					bindrows.Add(obj);

					TreeIter iter = NewRow();			
					for(int i = 0; i < gridColumns.Count; i++)
						SetColumnValue (iter, i, String.Empty);

					return bindrows.Count - 1;
				}
			}

			return -1;
		}

		public int DeleteRow(int row) 
		{
			if (row < 0)
				return -1; // should throw an exception - out of range

			TreeIter iter = TreeIter.Zero;
			if (store.IterNthChild(out iter, row) == false)
				return -1;

			IBindingList b = (IBindingList) resolvedDataSource;
			if (b.AllowRemove) {
				IList list = (IList) resolvedDataSource;
				bindrows.RemoveAt(row);
				store.Remove (ref iter);
				list.RemoveAt (row);

				return row;
			}

			return -1;
		}

		// sets the column count.  beware, it clears
		// use this if you are going to load each column and row yourself
		// instead of using DataBind() or DataLoad()
		public void SetColumnCount (int columnCount) 
		{
			Clear ();
			dataMember = "";
			dataSource = null;

			GLib.GType[] theTypes = new GLib.GType[columnCount];
			gridColumns = new ArrayList ();
			for (int col = 0; col < columnCount; col++) 
			{
				theTypes[col] = GLib.GType.String;
				gridColumns.Add (new DataGridColumn ());
			}
			store.ColumnTypes = theTypes;
		}

		// load data from a data table or data set
		public long DataBind () 
		{
			long rowsRetrieved = 0;

			Clear ();

			System.Object o = null;
			o = GetResolvedDataSource (DataSource, DataMember);
			resolvedDataSource = o;
			IEnumerable ie = (IEnumerable) o;
			ITypedList tlist = (ITypedList) o;
			TreeIter iter = new TreeIter ();
									
			PropertyDescriptorCollection pdc = tlist.GetItemProperties (new PropertyDescriptor[0]);
			gridColumns = new ArrayList(pdc.Count);

			// define the columns in the treeview store
			// based on the schema of the result
			GLib.GType[] theTypes = new GLib.GType[pdc.Count];
			for (int col = 0; col < pdc.Count; col++) {
				theTypes[col] = GLib.GType.String;
			}
			store.ColumnTypes = theTypes;

			bindrows = new ArrayList();

			int colndx = -1;
			foreach (PropertyDescriptor pd in pdc) {

				colndx ++;

				DataGridColumn gridCol = new DataGridColumn ();
				gridCol.ColumnName = pd.Name;		
				gridColumns.Add (gridCol);
			}

			bindrows = new ArrayList();

			foreach (System.Object obj in ie) {
				ICustomTypeDescriptor custom = (ICustomTypeDescriptor) obj;
				PropertyDescriptorCollection properties = custom.GetProperties ();

				bindrows.Add(obj);
				
				rowsRetrieved ++;
				iter = NewRow ();
				int cv = 0;
				foreach (PropertyDescriptor property in properties) {
					object oPropValue = property.GetValue (obj);
					string sPropValue = "";
					if (oPropValue.GetType ().ToString ().Equals("System.Byte[]"))  {
						//sPropValue = SqlSharpGtk.GetHexString ((byte[]) oPropValue);
						Console.Error.WriteLine("Byte[]  value");
					}
					else
						sPropValue = oPropValue.ToString ();
										
					SetColumnValue (iter, cv, sPropValue);
					cv++;			
				}
			}

			treeView.Model = store;
			AutoCreateTreeViewColumns ();
			return rowsRetrieved;
		}

		// borrowed from Mono's System.Web implementation
		protected IEnumerable GetResolvedDataSource(object source, string member) 
		{
			if (source != null && source is IListSource) {
				IListSource src = (IListSource) source;
				IList list = src.GetList ();
				if (!src.ContainsListCollection) {
					return list;
				}
				if (list != null && list is ITypedList) {

					ITypedList tlist = (ITypedList) list;
					PropertyDescriptorCollection pdc = tlist.GetItemProperties (new PropertyDescriptor[0]);
					if (pdc != null && pdc.Count > 0) {
						PropertyDescriptor pd = null;
						if (member != null && member.Length > 0) {
							pd = pdc.Find (member, true);
						} else {
							pd = pdc[0];
						}
						if (pd != null) {
							object rv = pd.GetValue (list[0]);
							if (rv != null && rv is IEnumerable) {
								return (IEnumerable)rv;
							}
						}
						throw new Exception ("ListSource_Missing_DataMember");
					}
					throw new Exception ("ListSource_Without_DataMembers");
				}
			}
			if (source is IEnumerable) {
				return (IEnumerable)source;
			}
			return null;
		}

		public void Clear () 
		{
			if (store != null) 
			{
				store.Clear ();
				store = null;
				store = new ListStore (GLib.GType.String);
			}
			else
				store = new ListStore (GLib.GType.String);

			if (gridColumns != null) 
			{
				for (int c = 0; c < gridColumns.Count; c++) 
				{
					DataGridColumn gridCol = (DataGridColumn) gridColumns[c];
					if (gridCol.TreeViewColumn != null) 
					{
						treeView.RemoveColumn (gridCol.TreeViewColumn);
						gridCol.TreeViewColumn = null;
					}
				}
				gridColumns.Clear ();
				gridColumns = null;
			}
		}

		public TreeIter NewRow () 
		{ 
			return store.Append();
		}

		public void AddRow (object[] columnValues) 
		{	
			TreeIter iter = NewRow ();			
			for(int col = 0; col < columnValues.Length; col++) {
				string cellValue = columnValues[col].ToString ();
				SetColumnValue (iter, col, cellValue);
			}
		}

		public void SetColumnValue (TreeIter iter, int column, string value) 
		{
			GLib.Value cell = new GLib.Value (value);
			store.SetValue (iter, column, cell);	
		}

		public void SetColumnValue (TreeIter iter, int column, byte[] value) 
		{
			//string svalue = SqlSharpGtk.GetHexString (value);
			//SetColumnValue (iter, column, svalue);
		}

		private void AutoCreateTreeViewColumns () 
		{
			for(int col = 0; col < gridColumns.Count; col++) {
				// escape underscore _ because it is used
				// as the underline in menus and labels
				StringBuilder name = new StringBuilder ();
				foreach (char ch in ((DataGridColumn) gridColumns[col]).ColumnName) {
					if (ch == '_')
						name.Append ("__");
					else
						name.Append (ch);
				}
				TreeViewColumn tvc = CreateColumn (col, name.ToString ());
				AppendColumn (tvc);
			}
		}

		public int AppendColumn(TreeViewColumn tvc) 
		{
			return treeView.AppendColumn (tvc);
		}

		private void TextCellEdited (object o, EditedArgs args) 
		{
			IBindingList b = (IBindingList) resolvedDataSource;
			if (b.AllowEdit) {
				// ITypedList may help you figure out how to convert
				// between different data types
				// such as, how to display numbers, dates, etc...

				TreePath path = new TreePath (args.Path);
				TreeIter iter;
				store.GetIter (out iter, path);
				int i = path.Indices[0];
			
				TreePath cpath;
				string cellValue = args.NewText;

				TreeViewColumn tvcolumn;
				treeView.GetCursor (out cpath, out tvcolumn);
				int c = 0;
				for(c = 0; c < gridColumns.Count; c++) {
					TreeViewColumn tvc = ((DataGridColumn) gridColumns[c]).TreeViewColumn;
					if (tvcolumn == tvc) {
						Console.Error.WriteLine("Column clicked:  Column Name: " + tvcolumn.Title);
						Console.Error.WriteLine("     Ordinal: " + c.ToString());
						break;
					}
				}

				if (c >= gridColumns.Count)
					Console.Error.WriteLine("tv col not found");

				ICustomTypeDescriptor custom = (ICustomTypeDescriptor) bindrows[i];
				PropertyDescriptorCollection properties = custom.GetProperties ();
				PropertyDescriptor pd = properties[c];
				pd.SetValue(bindrows[i], cellValue);
			
				Console.Error.WriteLine("    Row number: " + path.Indices[0].ToString());
				Console.Error.WriteLine("    Cell Value: " + cellValue);
			
				((IEditableObject) bindrows[i]).BeginEdit();
				SetColumnValue(iter, c, cellValue);
				((IEditableObject) bindrows[i]).EndEdit();
			}
		}

		public TreeViewColumn CreateColumn (int columnNum, string columnName) 
		{
			TreeViewColumn treeViewCol = new TreeViewColumn ();		 
			CellRendererText renderer = new CellRendererText ();
			treeViewCol.Clickable = true;
			treeView.RulesHint = true;
			
			treeView.Selection.Mode = SelectionMode.Single;
			//treeView.Selection.Mode = SelectionMode.Multiple;

			// Editable, Activatable, Inert
			renderer.Mode = CellRendererMode.Editable;
			//renderer.Family = "courier new";
			renderer.Editable = true;
			renderer.Edited += new EditedHandler (TextCellEdited);
			treeViewCol.Title = columnName;
			treeViewCol.PackStart (renderer, true);
			treeViewCol.AddAttribute (renderer, "text", columnNum);

			DataGridColumn gridCol = (DataGridColumn) gridColumns[columnNum];
			gridCol.Renderer = renderer;
			gridCol.TreeViewColumn = treeViewCol;
			
			return treeViewCol;
		}
	}
}



More information about the Gtk-sharp-list mailing list