[Mono-list] GTK# DataGrid sample

Andrus kobruleht2 at hot.ee
Sun Oct 29 05:01:00 EST 2006


Daniel,

thank you.
I found the following disadvantages of this code compared to SWF:

1. As you wrote, this is only one-way binding.
2. Requires lot of manually written code.
3. Unfinished, not documented and tested.

In case of WinForms I need to write manually only 3 lines for two-way data 
binding:

Command1.CommandText = "select * FROM mytable";
DataAdapter1.Fill(dataSet1);
DataSource = dataSet1.Tables[0];

Other code is generated by free Visual C# Express 2005  automatically and 
works in MONO.

I have no experience to develop this in GTK#
So I think I will try use WinForms data binding.

Thank you very much for this sample. Now I understand that this can be 
implemented in GTK# also

Andrus.

----- Original Message ----- 

>I have something I have worked on for awhile.
>
> Here are the source files I included:
> DataGrid.cs - creates a DataGrid for Gtk# with data
> binding support.
> TestDataGrid.cs - tests the gtk# data grid
>
> Basically, you can take a pre-loaded DataTable, and
> then "data bind" it to the DataGrid.  It may not be
> true data binding like SWF or webforms, but its an
> attempt.
>
> A change to the data in the DataGrid will update the
> data in the DataTable.
> If you add a row or delete a row in the DataGrid, it
> will be reflected in the DataTable.  If you modify a
> cell in the DataGrid, the row and column in the
> DataTable will be updated.  However, modifying
> something in the DataTable does not update the
> DataGrid.
>
> In the test, there are four menu items:
> 1. Add Row - adds a row
> 2. Dump Table - dumps to the console what's in the
> DataTable
> 3. Editable - sets the DataGrid editable or not
> 4. Delete Selected Row - deletes the highlighted row
>
> The DataGrid is implemented using a Gtk# TreeView
> using the ListStore tree model.
>
>> I need to edit DataTable returned by Npgsql in grid.
>> I'm studying GTK# and WinForms DataGrid  for this.
>> It would be nice if sqlsharpgtk allows edit tables
>> in grid.
>> I was looking for a sample GTK# code which allows to
>> edit DataTable in grid
>> but have'nt found any.
>> So I think I will use WinForms.



--------------------------------------------------------------------------------


> // 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;
> }
> }
> }
>
>


--------------------------------------------------------------------------------


> // $ 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;
> }
> }
> }
>
>



More information about the Mono-list mailing list