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 {
88 [DataCategory ("Data")]
89 [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows edits.")]
91 public bool AllowEdit {
100 [DataCategory ("Data")]
101 [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows new rows to be added.")]
102 [DefaultValue (true)]
103 public bool AllowNew {
113 [DataCategory ("Data")]
114 [DataSysDescription ("Indicates whether to use the default sort if the Sort property is not set.")]
115 [DefaultValue (false)]
116 [RefreshProperties (RefreshProperties.All)]
117 public bool ApplyDefaultSort {
120 return applyDefaultSort;
125 applyDefaultSort = value;
126 // FIXME: update the index cache to the DataTable, and
127 // only refresh the index when the DataTable
128 // has changes via column, row, or constraint
134 // get the count of rows in the DataView after RowFilter
135 // and RowStateFilter have been applied
137 [DataSysDescription ("Returns the number of items currently in this view.")]
141 // FIXME: remove this line once collection change
142 // events from the DataTable are handled
145 return rowCache.Length;;
150 [DataSysDescription ("This returns a pointer to back to the DataViewManager that owns this DataSet (if any).")]
151 public DataViewManager DataViewManager {
154 return dataViewManager;
159 // the compiler creates a DefaultMemeberAttribute from
160 // this IndexerNameAttribute
161 [System.Runtime.CompilerServices.IndexerName("Item")]
162 public DataRowView this[int recordIndex] {
165 // FIXME: use index cache to the DataTable, and
166 // only refresh the index when the DataTable
167 // has changes via column, row, or constraint
169 // Remove this line once changed events are handled
172 return rowCache[recordIndex];
176 [DataCategory ("Data")]
177 [DataSysDescription ("Indicates an expression used to filter the data returned by this DataView.")]
179 public virtual string RowFilter {
188 // FIXME: update the index cache to the DataTable, and
189 // only refresh the index when the DataTable
190 // has changes via column, row, or constraint
196 [DataCategory ("Data")]
197 [DataSysDescription ("Indicates the versions of data returned by this DataView.")]
198 [DefaultValue (DataViewRowState.CurrentRows)]
199 public DataViewRowState RowStateFilter {
208 // FIXME: update the index cache to the DataTable, and
209 // only refresh the index when the DataTable
210 // has changes via column, row, or constraint
216 [DataCategory ("Data")]
217 [DataSysDescription ("Indicates the order in which data is returned by this DataView.")]
228 // FIXME: update the index cache to the DataTable, and
229 // only refresh the index when the DataTable
230 // has changes via column, row, or constraint
236 [DataCategory ("Data")]
237 [DataSysDescription ("Indicates the table this DataView uses to get data.")]
238 [DefaultValue (null)]
239 [RefreshProperties (RefreshProperties.All)]
240 public DataTable Table {
249 // FIXME: update the index cache to the DataTable, and
250 // only refresh the index when the DataTable
251 // has changes via column, row, or constraint
258 public virtual DataRowView AddNew()
261 throw new DataException ("DataView is not open.");
263 throw new DataException ("Cannot call AddNew on a DataView where AllowNew is false.");
265 DataRow row = dataTable.NewRow ();
266 DataRowView view = new DataRowView (this, row);
268 dataTable.Rows.Add (row);
271 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, rowCache.Length));
276 public void BeginInit()
283 public void CopyTo (Array array, int index)
285 // FIXME: use index cache to the DataTable, and
286 // only refresh the index when the DataTable
287 // has changes via column, row, or constraint
292 for (; row < rowCache.Length && row < array.Length; row++) {
293 array.SetValue (rowCache[row], index + row);
295 if (row < array.Length) {
296 for (int r = 0; r < array.Length; r++) {
297 array.SetValue (null, index + r);
302 public void Delete(int index)
305 throw new DataException ("DataView is not open.");
307 throw new DataException ("Cannot delete on a DataSource where AllowDelete is false.");
311 if (index > rowCache.Length)
312 throw new IndexOutOfRangeException ("There is no row at " +
313 "position: " + index + ".");
315 DataRowView row = rowCache [index];
318 OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index));
323 public virtual bool Equals (DataView dv)
325 throw new NotImplementedException ();
330 public void EndInit()
337 public int Find(object key)
339 // FIXME: use index cache to the DataTable, and
340 // only refresh the index when the DataTable
341 // has changes via column, row, or constraint
344 throw new NotImplementedException ();
348 public int Find(object[] key)
350 // FIXME: use an index cache to the DataTable, and
351 // only refresh the index when the DataTable
352 // has changes via column, row, or constraint
355 throw new NotImplementedException ();
359 public DataRowView[] FindRows(object key)
361 // FIXME: use an index cache to the DataTable, and
362 // only refresh the index when the DataTable
363 // has changes via column, row, or constraint
366 throw new NotImplementedException ();
370 public DataRowView[] FindRows(object[] key)
372 // FIXME: use an index cache to the DataTable, and
373 // only refresh the index when the DataTable
374 // has changes via column, row, or constraint
377 throw new NotImplementedException ();
381 public IEnumerator GetEnumerator()
383 // FIXME: use an index cache to the DataTable, and
384 // only refresh the index when the DataTable
385 // has changes via column, row, or constraint
389 return new DataViewEnumerator (rowCache);
393 [DataCategory ("Data")]
394 [DataSysDescription ("Indicates the data returned by this DataView has somehow changed.")]
395 public event ListChangedEventHandler ListChanged;
397 protected bool IsOpen {
405 protected void Close()
412 protected virtual void ColumnCollectionChanged (object sender,
413 CollectionChangeEventArgs e)
415 throw new NotImplementedException ();
418 protected override void Dispose (bool disposing)
423 base.Dispose (disposing);
427 protected virtual void IndexListChanged(object sender, ListChangedEventArgs e)
429 throw new NotImplementedException ();
433 protected virtual void OnListChanged(ListChangedEventArgs e)
436 if (ListChanged != null)
437 ListChanged (this, e);
443 protected void Open()
445 // FIXME: create the initial index cache to the DataTable, and
446 // only refresh the index when the DataTable
447 // has changes via column, row, or constraint
448 // changed events. the index cache is generally
449 // a DataViewRow array that points to the actual
450 // DataRows in the this DataTable's DataRowCollection;
451 // this index is really a cache that gets
452 // created during Open(), gets Updated
453 // when various properties of this view
454 // changes, gets Updated when this DataTable's
455 // row, column, or constraint collections have changed.
456 // I'm not sure what else.
457 // The data view will know one of the DataTable's
458 // collections have changed via one of
459 // its changed events.
460 // Otherwise, if getting a/the DataRowView(s),
461 // Count, or other properties, then just use the
467 // internal use by Mono
468 protected void Reset()
\r
470 // TODO: what really happens?
\r
474 OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1));
479 public DataTable ToTable ()
481 throw new NotImplementedException ();
485 public DataTable ToTable (bool isDistinct, string[] columnNames)
487 throw new NotImplementedException ();
491 // internal use by Mono
492 protected virtual void UpdateIndex ()
\r
494 UpdateIndex (false);
\r
497 // This is method is internal to
498 // the Mono implementation of DataView; it
499 // is not to be used from your code.
501 // Update the DataRowView array which is an index cache
502 // into the DataTable's DataRowCollection.
504 // I assume this is what UpdateIndex is used for
505 protected virtual void UpdateIndex(bool force)
507 DataRowView[] newRowCache = null;
508 DataRow[] rows = null;
510 rows = dataTable.Select (RowFilter, Sort, RowStateFilter);
512 newRowCache = new DataRowView[rows.Length];
513 for (int r = 0; r < rows.Length; r++) {
514 newRowCache[r] = new DataRowView (this, rows[r]);
516 rowCache = newRowCache;
520 PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors)
522 // FIXME: use listAccessors somehow
524 DataColumnPropertyDescriptor[] descriptors =
525 new DataColumnPropertyDescriptor[dataTable.Columns.Count];
527 DataColumnPropertyDescriptor descriptor;
528 DataColumn dataColumn;
529 for (int col = 0; col < dataTable.Columns.Count; col ++)
531 dataColumn = dataTable.Columns[col];
533 descriptor = new DataColumnPropertyDescriptor(
534 dataColumn.ColumnName, col, null);
535 descriptor.SetComponentType (typeof (System.Data.DataRowView));
536 descriptor.SetPropertyType (dataColumn.DataType);
537 descriptor.SetReadOnly (dataColumn.ReadOnly);
539 descriptors[col] = descriptor;
542 return new PropertyDescriptorCollection (descriptors);
546 string ITypedList.GetListName (PropertyDescriptor[] listAccessors)
551 //int ICollection.Count {
557 bool ICollection.IsSynchronized {
564 object ICollection.SyncRoot {
572 //void ICollection.CopyTo (Array array, int index)
574 // CopyTo (array, index);
577 bool IList.IsFixedSize {
584 bool IList.IsReadOnly {
591 object IList.this[int recordIndex] {
594 return this[recordIndex];
599 throw new InvalidOperationException();
604 int IList.Add (object value)
606 throw new NotImplementedException ();
612 throw new NotImplementedException ();
616 bool IList.Contains (object value)
618 throw new NotImplementedException ();
622 int IList.IndexOf (object value)
624 throw new NotImplementedException ();
628 void IList.Insert(int index,object value)
630 throw new NotImplementedException ();
634 void IList.Remove(object value)
636 throw new NotImplementedException ();
640 void IList.RemoveAt(int index)
642 throw new NotImplementedException ();
645 #region IBindingList implementation
648 void IBindingList.AddIndex (PropertyDescriptor property)
650 throw new NotImplementedException ();
654 object IBindingList.AddNew ()
656 throw new NotImplementedException ();
660 void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)
662 throw new NotImplementedException ();
666 int IBindingList.Find (PropertyDescriptor property, object key)
668 throw new NotImplementedException ();
672 void IBindingList.RemoveIndex (PropertyDescriptor property)
674 throw new NotImplementedException ();
678 void IBindingList.RemoveSort ()
680 throw new NotImplementedException ();
683 bool IBindingList.AllowEdit {
690 bool IBindingList.AllowNew {
697 bool IBindingList.AllowRemove {
704 bool IBindingList.IsSorted {
711 ListSortDirection IBindingList.SortDirection {
715 return ListSortDirection.Ascending;
719 PropertyDescriptor IBindingList.SortProperty {
727 bool IBindingList.SupportsChangeNotification {
734 bool IBindingList.SupportsSearching {
741 bool IBindingList.SupportsSorting {
748 #endregion // IBindingList implementation
750 private class DataViewEnumerator : IEnumerator
752 private DataRowView[] rows;
755 internal DataViewEnumerator (DataRowView[] dataRowViews)
760 public object Current {
762 if (on == -1 || on >= rows.Length)
763 throw new InvalidOperationException ();
768 public bool MoveNext ()
770 // TODO: how do you determine
771 // if a collection has been
773 if (on < rows.Length - 1) {
781 public void Reset () {