2 // DataGrid - attempt at creating a DataGrid for GTK#
3 // using a GTK# TreeView. The goal is to have similar
4 // functionality to a System.Windows.Forms.DataGrid
5 // or System.Web.UI.WebControls.DataGrid. This includes
6 // data binding support.
8 // Based on the sample/TreeViewDemo.cs
10 // Author: Kristian Rietveld <kris@gtk.org>
11 // Daniel Morgan <danmorg@sc.rr.com>
13 // (c) 2002 Kristian Rietveld
14 // (c) 2002 Daniel Morgan
17 namespace Gtk.Controls
20 using System.Collections;
21 using System.ComponentModel;
23 using System.Reflection;
30 using System.Runtime.InteropServices;
32 public class DataGridColumn
34 private string columnName = "";
35 private TreeViewColumn treeViewColumn = null;
37 public string ColumnName {
46 public TreeViewColumn TreeViewColumn {
48 return treeViewColumn;
51 treeViewColumn = value;
56 public class DataGrid : VBox
58 private ListStore store = null;
59 private TreeView treeView = null;
61 public DataGridColumn[] gridColumns = null;
63 public DataGrid () : base(false, 4)
65 ScrolledWindow sw = new ScrolledWindow ();
66 this.PackStart (sw, true, true, 0);
68 treeView = new TreeView (store);
69 treeView.HeadersVisible = true;
74 // FIXME: need to place in a base class
75 // the DataSource, DataMember, DataBind()
77 // maybe we can call the base class
78 // BaseDataList for GTK#?
80 private object dataSource = null;
82 private string dataMember = "";
84 public object DataSource {
93 public string DataMember {
102 public void DataBind ()
106 System.Object o = null;
107 o = GetResolvedDataSource (DataSource, DataMember);
108 IEnumerable ie = (IEnumerable) o;
109 ITypedList tlist = (ITypedList) o;
111 // FIXME: does not belong in this base method
112 TreeIter iter = new TreeIter ();
114 PropertyDescriptorCollection pdc = tlist.GetItemProperties (new PropertyDescriptor[0]);
116 // FIXME: does not belong in this base method
117 gridColumns = new DataGridColumn[pdc.Count];
119 // FIXME: does not belong in base method
120 // define the columns in the treeview store
121 // based on the schema of the result
122 uint[] theTypes = new uint[pdc.Count];
123 for (int col = 0; col < pdc.Count; col++) {
124 theTypes[col] = (int) TypeFundamentals.TypeString;
126 store.SetColumnTypes (theTypes);
128 // FIXME: does not belong in this base method
130 foreach (PropertyDescriptor pd in pdc) {
132 gridColumns[colndx] = new DataGridColumn ();
133 gridColumns[colndx].ColumnName = pd.Name;
136 foreach (System.Object obj in ie) {
137 ICustomTypeDescriptor custom = (ICustomTypeDescriptor) obj;
138 PropertyDescriptorCollection properties;
139 properties = custom.GetProperties ();
143 foreach (PropertyDescriptor property in properties) {
144 object oPropValue = property.GetValue (obj);
145 string sPropValue = oPropValue.ToString ();
147 // FIXME: does not belong in this base method
148 SetColumnValue (iter, cv, sPropValue);
154 // FIXME: does not belong in this base method
155 treeView.Model = store;
156 AutoCreateTreeViewColumns (treeView);
159 // borrowed from Mono's System.Web implementation
160 protected IEnumerable GetResolvedDataSource(object source, string member)
162 if (source != null && source is IListSource) {
163 IListSource src = (IListSource) source;
164 IList list = src.GetList ();
165 if (!src.ContainsListCollection) {
168 if (list != null && list is ITypedList) {
170 ITypedList tlist = (ITypedList) list;
171 PropertyDescriptorCollection pdc = tlist.GetItemProperties (new PropertyDescriptor[0]);
172 if (pdc != null && pdc.Count > 0) {
173 PropertyDescriptor pd = null;
174 if (member != null && member.Length > 0) {
175 pd = pdc.Find (member, true);
180 object rv = pd.GetValue (list[0]);
181 if (rv != null && rv is IEnumerable) {
182 return (IEnumerable)rv;
185 throw new Exception ("ListSource_Missing_DataMember");
187 throw new Exception ("ListSource_Without_DataMembers");
190 if (source is IEnumerable) {
191 return (IEnumerable)source;
201 store = new ListStore ((int)TypeFundamentals.TypeString);
204 store = new ListStore ((int)TypeFundamentals.TypeString);
206 if (gridColumns != null) {
207 for (int c = 0; c < gridColumns.Length; c++) {
208 if (gridColumns[c] != null) {
209 if (gridColumns[c].TreeViewColumn != null) {
210 treeView.RemoveColumn (gridColumns[c].TreeViewColumn);
211 gridColumns[c].TreeViewColumn = null;
213 gridColumns[c] = null;
221 public void AppendText (string text)
223 Console.WriteLine ("DataGrid DEBUG: " + text);
224 Console.Out.Flush ();
227 public TreeIter NewRow ()
229 TreeIter rowTreeIter = new TreeIter();
230 store.Append (out rowTreeIter);
234 public void AddRow (object[] columnValues)
236 TreeIter iter = NewRow ();
237 for(int col = 0; col < columnValues.Length; col++) {
238 string cellValue = columnValues[col].ToString ();
239 SetColumnValue (iter, col, cellValue);
243 public void SetColumnValue (TreeIter iter, int column, string value)
245 GLib.Value cell = new GLib.Value (value);
246 store.SetValue (iter, column, cell);
249 private void AutoCreateTreeViewColumns (TreeView theTreeView)
251 for(int col = 0; col < gridColumns.Length; col++) {
252 // escape underscore _ because it is used
253 // as the underline in menus and labels
254 StringBuilder name = new StringBuilder ();
255 foreach (char ch in gridColumns[col].ColumnName) {
262 tvc = CreateColumn (theTreeView, col,
264 theTreeView.AppendColumn (tvc);
268 // TODO: maybe need to create
269 // a DataGridColumnCollection of DataGridColumn
270 // and a DataGridColumn contain a TreeViewColumn
271 public TreeViewColumn CreateColumn (TreeView theTreeView, int col,
274 TreeViewColumn NameCol = new TreeViewColumn ();
275 CellRenderer NameRenderer = new CellRendererText ();
277 NameCol.Title = columnName;
278 NameCol.PackStart (NameRenderer, true);
279 NameCol.AddAttribute (NameRenderer, "text", col);
281 gridColumns[col].TreeViewColumn = NameCol;