2 // System.Data.DataView.cs
5 // Daniel Morgan <danmorg@sc.rr.com>
6 // Tim Coleman (tim@timcoleman.com)
8 // Copyright (C) Daniel Morgan, 2002, 2003
9 // (C) Ximian, Inc 2002
10 // Copyright (C) Tim Coleman, 2002-2003
14 using System.Collections;
15 using System.ComponentModel;
16 using System.Reflection;
21 /// A DataView is used in the binding of data between
22 /// a DataTable and Windows Forms or Web Forms allowing
23 /// a view of a DataTable for editing, filtering,
24 /// navigation, searching, and sorting.
28 [DefaultEvent ("PositionChanged")]
29 [DefaultProperty ("Table")]
30 public class DataView : MarshalByValueComponent, IBindingList, IList, ICollection, IEnumerable, ITypedList, ISupportInitialize
32 DataTable dataTable = null;
33 string rowFilter = "";
35 DataViewRowState rowState;
36 DataRowView[] rowCache = null;
38 // FIXME: what are the default values?
40 bool allowEdit = true;
41 bool allowDelete = true;
42 bool applyDefaultSort = false;
43 bool isSorted = false;
49 internal DataViewManager dataViewManager = null;
53 dataTable = new DataTable ();
54 rowState = DataViewRowState.CurrentRows;
58 public DataView (DataTable table)
61 rowState = DataViewRowState.CurrentRows;
65 public DataView (DataTable table, string RowFilter,
66 string Sort, DataViewRowState RowState)
69 rowState = DataViewRowState.CurrentRows;
70 rowFilter = RowFilter;
76 [DataCategory ("Data")]
77 [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows deletes.")]
79 public bool AllowDelete {
91 [DataCategory ("Data")]
92 [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows edits.")]
94 public bool AllowEdit {
106 [DataCategory ("Data")]
107 [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows new rows to be added.")]
108 [DefaultValue (true)]
109 public bool AllowNew {
121 [DataCategory ("Data")]
122 [DataSysDescription ("Indicates whether to use the default sort if the Sort property is not set.")]
123 [DefaultValue (false)]
124 [RefreshProperties (RefreshProperties.All)]
125 public bool ApplyDefaultSort {
128 return applyDefaultSort;
133 applyDefaultSort = value;
134 // FIXME: update the index cache to the DataTable, and
135 // only refresh the index when the DataTable
136 // has changes via column, row, or constraint
142 // get the count of rows in the DataView after RowFilter
143 // and RowStateFilter have been applied
145 [DataSysDescription ("Returns the number of items currently in this view.")]
149 // FIXME: remove this line once collection change
150 // events from the DataTable are handled
153 return rowCache.Length;;
158 [DataSysDescription ("This returns a pointer to back to the DataViewManager that owns this DataSet (if any).")]
159 public DataViewManager DataViewManager {
162 return dataViewManager;
167 // the compiler creates a DefaultMemeberAttribute from
168 // this IndexerNameAttribute
169 [System.Runtime.CompilerServices.IndexerName("Item")]
170 public DataRowView this[int recordIndex] {
173 // FIXME: use index cache to the DataTable, and
174 // only refresh the index when the DataTable
175 // has changes via column, row, or constraint
177 // Remove this line once changed events are handled
180 return rowCache[recordIndex];
184 [DataCategory ("Data")]
185 [DataSysDescription ("Indicates an expression used to filter the data returned by this DataView.")]
187 public virtual string RowFilter {
196 // FIXME: update the index cache to the DataTable, and
197 // only refresh the index when the DataTable
198 // has changes via column, row, or constraint
204 [DataCategory ("Data")]
205 [DataSysDescription ("Indicates the versions of data returned by this DataView.")]
206 [DefaultValue (DataViewRowState.CurrentRows)]
207 public DataViewRowState RowStateFilter {
216 // FIXME: update the index cache to the DataTable, and
217 // only refresh the index when the DataTable
218 // has changes via column, row, or constraint
224 [DataCategory ("Data")]
225 [DataSysDescription ("Indicates the order in which data is returned by this DataView.")]
236 // FIXME: update the index cache to the DataTable, and
237 // only refresh the index when the DataTable
238 // has changes via column, row, or constraint
244 [DataCategory ("Data")]
245 [DataSysDescription ("Indicates the table this DataView uses to get data.")]
246 [DefaultValue (null)]
247 [RefreshProperties (RefreshProperties.All)]
248 public DataTable Table {
257 // FIXME: update the index cache to the DataTable, and
258 // only refresh the index when the DataTable
259 // has changes via column, row, or constraint
266 public virtual DataRowView AddNew()
269 throw new DataException ("DataView is not open.");
271 throw new DataException ("Cannot call AddNew on a DataView where AllowNew is false.");
273 DataRow row = dataTable.NewRow ();
274 DataRowView view = new DataRowView (this, row);
276 dataTable.Rows.Add (row);
279 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, rowCache.Length));
284 public void BeginInit()
291 public void CopyTo (Array array, int index)
293 // FIXME: use index cache to the DataTable, and
294 // only refresh the index when the DataTable
295 // has changes via column, row, or constraint
300 for (; row < rowCache.Length && row < array.Length; row++) {
301 array.SetValue (rowCache[row], index + row);
303 if (row < array.Length) {
304 for (int r = 0; r < array.Length; r++) {
305 array.SetValue (null, index + r);
310 public void Delete(int index)
313 throw new DataException ("DataView is not open.");
315 throw new DataException ("Cannot delete on a DataSource where AllowDelete is false.");
319 if (index > rowCache.Length)
320 throw new IndexOutOfRangeException ("There is no row at " +
321 "position: " + index + ".");
323 DataRowView row = rowCache [index];
326 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index));
331 public virtual bool Equals (DataView dv)
333 throw new NotImplementedException ();
338 public void EndInit()
345 public int Find(object key)
347 // FIXME: use index cache to the DataTable, and
348 // only refresh the index when the DataTable
349 // has changes via column, row, or constraint
352 throw new NotImplementedException ();
356 public int Find(object[] key)
358 // FIXME: use an index cache to the DataTable, and
359 // only refresh the index when the DataTable
360 // has changes via column, row, or constraint
363 throw new NotImplementedException ();
367 public DataRowView[] FindRows(object key)
369 // FIXME: use an index cache to the DataTable, and
370 // only refresh the index when the DataTable
371 // has changes via column, row, or constraint
374 throw new NotImplementedException ();
378 public DataRowView[] FindRows(object[] key)
380 // FIXME: use an index cache to the DataTable, and
381 // only refresh the index when the DataTable
382 // has changes via column, row, or constraint
385 throw new NotImplementedException ();
389 public IEnumerator GetEnumerator()
391 // FIXME: use an index cache to the DataTable, and
392 // only refresh the index when the DataTable
393 // has changes via column, row, or constraint
397 return new DataViewEnumerator (rowCache);
401 [DataCategory ("Data")]
402 [DataSysDescription ("Indicates the data returned by this DataView has somehow changed.")]
403 public event ListChangedEventHandler ListChanged;
405 protected bool IsOpen {
413 protected void Close()
420 protected virtual void ColumnCollectionChanged (object sender,
421 CollectionChangeEventArgs e)
423 throw new NotImplementedException ();
426 protected override void Dispose (bool disposing)
431 base.Dispose (disposing);
435 protected virtual void IndexListChanged(object sender, ListChangedEventArgs e)
437 throw new NotImplementedException ();
441 protected virtual void OnListChanged(ListChangedEventArgs e)
444 if (ListChanged != null)
445 ListChanged (this, e);
451 protected void Open()
453 // FIXME: create the initial index cache to the DataTable, and
454 // only refresh the index when the DataTable
455 // has changes via column, row, or constraint
456 // changed events. the index cache is generally
457 // a DataViewRow array that points to the actual
458 // DataRows in the this DataTable's DataRowCollection;
459 // this index is really a cache that gets
460 // created during Open(), gets Updated
461 // when various properties of this view
462 // changes, gets Updated when this DataTable's
463 // row, column, or constraint collections have changed.
464 // I'm not sure what else.
465 // The data view will know one of the DataTable's
466 // collections have changed via one of
467 // its changed events.
468 // Otherwise, if getting a/the DataRowView(s),
469 // Count, or other properties, then just use the
475 // internal use by Mono
476 protected void Reset()
\r
478 // TODO: what really happens?
\r
482 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1));
487 public DataTable ToTable ()
489 throw new NotImplementedException ();
493 public DataTable ToTable (bool isDistinct, string[] columnNames)
495 throw new NotImplementedException ();
499 // internal use by Mono
500 protected virtual void UpdateIndex ()
\r
502 UpdateIndex (false);
\r
505 // This is method is internal to
506 // the Mono implementation of DataView; it
507 // is not to be used from your code.
509 // Update the DataRowView array which is an index cache
510 // into the DataTable's DataRowCollection.
512 // I assume this is what UpdateIndex is used for
513 protected virtual void UpdateIndex(bool force)
515 DataRowView[] newRowCache = null;
516 DataRow[] rows = null;
518 rows = dataTable.Select (RowFilter, Sort, RowStateFilter);
520 newRowCache = new DataRowView[rows.Length];
521 for (int r = 0; r < rows.Length; r++) {
522 newRowCache[r] = new DataRowView (this, rows[r]);
524 rowCache = newRowCache;
528 PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors)
530 // FIXME: use listAccessors somehow
532 DataColumnPropertyDescriptor[] descriptors =
533 new DataColumnPropertyDescriptor[dataTable.Columns.Count];
535 DataColumnPropertyDescriptor descriptor;
536 DataColumn dataColumn;
537 for (int col = 0; col < dataTable.Columns.Count; col ++)
539 dataColumn = dataTable.Columns[col];
541 descriptor = new DataColumnPropertyDescriptor(
542 dataColumn.ColumnName, col, null);
543 descriptor.SetComponentType (typeof (System.Data.DataRowView));
544 descriptor.SetPropertyType (dataColumn.DataType);
545 descriptor.SetReadOnly (dataColumn.ReadOnly);
547 descriptors[col] = descriptor;
550 return new PropertyDescriptorCollection (descriptors);
554 string ITypedList.GetListName (PropertyDescriptor[] listAccessors)
559 //int ICollection.Count {
565 bool ICollection.IsSynchronized {
572 object ICollection.SyncRoot {
580 //void ICollection.CopyTo (Array array, int index)
582 // CopyTo (array, index);
585 bool IList.IsFixedSize {
592 bool IList.IsReadOnly {
599 object IList.this[int recordIndex] {
602 return this[recordIndex];
607 throw new InvalidOperationException();
612 int IList.Add (object value)
614 throw new NotImplementedException ();
620 throw new NotImplementedException ();
624 bool IList.Contains (object value)
626 throw new NotImplementedException ();
630 int IList.IndexOf (object value)
632 throw new NotImplementedException ();
636 void IList.Insert(int index,object value)
638 throw new NotImplementedException ();
642 void IList.Remove(object value)
644 throw new NotImplementedException ();
648 void IList.RemoveAt(int index)
650 throw new NotImplementedException ();
653 #region IBindingList implementation
656 void IBindingList.AddIndex (PropertyDescriptor property)
658 throw new NotImplementedException ();
662 object IBindingList.AddNew ()
664 throw new NotImplementedException ();
668 void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)
670 throw new NotImplementedException ();
674 int IBindingList.Find (PropertyDescriptor property, object key)
676 throw new NotImplementedException ();
680 void IBindingList.RemoveIndex (PropertyDescriptor property)
682 throw new NotImplementedException ();
686 void IBindingList.RemoveSort ()
688 throw new NotImplementedException ();
691 bool IBindingList.AllowEdit {
698 bool IBindingList.AllowNew {
705 bool IBindingList.AllowRemove {
712 bool IBindingList.IsSorted {
719 ListSortDirection IBindingList.SortDirection {
723 return ListSortDirection.Ascending;
727 PropertyDescriptor IBindingList.SortProperty {
735 bool IBindingList.SupportsChangeNotification {
742 bool IBindingList.SupportsSearching {
749 bool IBindingList.SupportsSorting {
756 #endregion // IBindingList implementation
758 private class DataViewEnumerator : IEnumerator
760 private DataRowView[] rows;
763 internal DataViewEnumerator (DataRowView[] dataRowViews)
768 public object Current {
770 if (on == -1 || on >= rows.Length)
771 throw new InvalidOperationException ();
776 public bool MoveNext ()
778 // TODO: how do you determine
779 // if a collection has been
781 if (on < rows.Length - 1) {
789 public void Reset () {