DataView.cs :  » 2.6.4-mono-.net-core » System.Data » System » Data » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Data 
System.Data » System » Data » DataView.cs
//
// System.Data.DataView.cs
//
// Author:
//    Daniel Morgan <danmorg@sc.rr.com>
//    Tim Coleman (tim@timcoleman.com)
//    Punit Todi (punits_mailbox@yahoo.com)
//    Atsushi Enomoto <atsushi@ximian.com>
//    Konstantin Triger (kostat@mainsoft.com)
//
// Copyright (C) Daniel Morgan, 2002, 2003
// (C) Ximian, Inc 2002
// Copyright (C) Tim Coleman, 2002-2003

using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Data.Common;
using System.Globalization;
using Mono.Data.SqlExpressions;
using System.Text;

namespace System.Data{
  /// <summary>
  /// A DataView is used in the binding of data between
  /// a DataTable and Windows Forms or Web Forms allowing
  /// a view of a DataTable for editing, filtering,
  /// navigation, searching, and sorting.
  /// </summary>
  //[Designer]
  [Editor ("Microsoft.VSDesigner.Data.Design.DataSourceEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
     "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
  [DefaultEvent ("PositionChanged")]
  [DefaultProperty ("Table")]
  [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataViewDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
  public partial class DataView : MarshalByValueComponent, IEnumerable, ISupportInitialize {
    internal DataTable dataTable;
    string rowFilter = String.Empty;
    IExpression rowFilterExpr;
    string sort = String.Empty;
    ListSortDirection [] sortOrder;
    PropertyDescriptor sortProperty;
    DataColumn [] sortColumns;
    internal DataViewRowState rowState;
    internal DataRowView[] rowCache = new DataRowView [0];

    // BeginInit() support
    bool isInitPhase;
    bool inEndInit;
    DataTable initTable;
    bool initApplyDefaultSort;
    string initSort;
    string initRowFilter;
    DataViewRowState initRowState;

    // FIXME: what are the default values?
    bool allowNew = true;
    bool allowEdit = true;
    bool allowDelete = true;
    bool applyDefaultSort;
    //bool isSorted = false;

    bool isOpen;

    bool useDefaultSort = true;

    Index _index;
    internal DataRow _lastAdded;

    private DataViewManager dataViewManager;
    internal static ListChangedEventArgs ListResetEventArgs = new ListChangedEventArgs (ListChangedType.Reset,-1,-1);

    public DataView ()
    {
      rowState = DataViewRowState.CurrentRows;
      Open ();
    }

    public DataView (DataTable table)
      : this (table, (DataViewManager) null)
    {
    }

    internal DataView (DataTable table, DataViewManager manager)
    {
      dataTable = table;
      rowState = DataViewRowState.CurrentRows;
      dataViewManager = manager;
      Open ();
    }

    public DataView (DataTable table, string RowFilter,
      string Sort, DataViewRowState RowState)
      : this (table, null, RowFilter, Sort, RowState)
    {
    }

    internal DataView (DataTable table, DataViewManager manager,
      string RowFilter, string Sort, DataViewRowState RowState)
    {
      dataTable = table;
      dataViewManager = manager;
      rowState = DataViewRowState.CurrentRows;
      this.RowFilter = RowFilter;
      this.Sort = Sort;
      rowState = RowState;
      Open ();
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows deletes.")]
#endif
    [DefaultValue (true)]
    public bool AllowDelete {
      get { return allowDelete; }
      set { allowDelete = value; }
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows edits.")]
#endif
    [DefaultValue (true)]
    public bool AllowEdit {
      get { return allowEdit; }
      set { allowEdit = value; }
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows new rows to be added.")]
#endif
    [DefaultValue (true)]
    public bool AllowNew {
      get { return allowNew; }
      set { allowNew = value; }
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates whether to use the default sort if the Sort property is not set.")]
#endif
    [DefaultValue (false)]
    [RefreshProperties (RefreshProperties.All)]
    public bool ApplyDefaultSort {
      get { return applyDefaultSort; }
      set {
        if (isInitPhase) {
          initApplyDefaultSort = value;
          return;
        }
        if (applyDefaultSort == value)
          return;

        applyDefaultSort = value;
        if (applyDefaultSort == true && (sort == null || sort == string.Empty))
          PopulateDefaultSort ();
        if (!inEndInit) {
          UpdateIndex (true);
          OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
        }
      }
    }
    // get the count of rows in the DataView after RowFilter
    // and RowStateFilter have been applied
    [Browsable (false)]
#if !NET_2_0
    [DataSysDescription ("Returns the number of items currently in this view.")]
#endif
    public int Count {
      get { return rowCache.Length; }
    }

    [Browsable (false)]
#if !NET_2_0
    [DataSysDescription ("This returns a pointer to back to the DataViewManager that owns this DataSet (if any).")]
#endif
    public DataViewManager DataViewManager {
      get { return dataViewManager; }
    }

    // Item indexer
    // the compiler creates a DefaultMemeberAttribute from
    // this IndexerNameAttribute
    [System.Runtime.CompilerServices.IndexerName("Item")]
    public DataRowView this [int recordIndex] {
      get {
        if (recordIndex > rowCache.Length)
          throw new IndexOutOfRangeException ("There is no row at position: " + recordIndex + ".");
        return rowCache [recordIndex];
      }
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates an expression used to filter the data returned by this DataView.")]
#endif
    [DefaultValue ("")]
    public virtual string RowFilter {
      get { return rowFilter; }
      set {
        if (value == null)
          value = String.Empty;
        if (isInitPhase) {
          initRowFilter = value;
          return;
        }

        CultureInfo info = (Table != null) ? Table.Locale : CultureInfo.CurrentCulture;
        if (String.Compare (rowFilter, value, false, info) == 0)
          return;

        if (value.Length == 0) {
          rowFilterExpr = null;
        } else {
          Parser parser = new Parser ();
          rowFilterExpr = parser.Compile (value);
        }
        rowFilter = value;
        if (!inEndInit) {
          UpdateIndex (true);
          OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
        }
      }
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates the versions of data returned by this DataView.")]
#endif
    [DefaultValue (DataViewRowState.CurrentRows)]
    public DataViewRowState RowStateFilter {
      get { return rowState; }
      set {
        if (isInitPhase) {
          initRowState = value;
          return;
        }

        if (value == rowState)
          return;

        rowState = value;
        if (!inEndInit) {
          UpdateIndex (true);
          OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
        }
      }
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates the order in which data is returned by this DataView.")]
#endif
    [DefaultValue ("")]
    public string Sort {
      get {
        if (useDefaultSort)
          return String.Empty;
        else
          return sort;
      }
      set {
        if (isInitPhase) {
          initSort = value;
          return;
        }
        if (value == sort)
          return;

        if (value == null || value.Length == 0) {
        /* if given value is null useDefaultSort */
          useDefaultSort = true;
          /* if ApplyDefault sort is true try appling it */
          if (ApplyDefaultSort)
            PopulateDefaultSort ();
        } else {
          /* else donot useDefaultSort. set it as false */
          /* sort is set to value specified */
          useDefaultSort = false;
          sort = value;
          //sortedColumns = SortableColumn.ParseSortString (dataTable, value, true);
        }

        if (!inEndInit) {
          UpdateIndex (true);
          OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
        }
      }
    }

    [TypeConverter (typeof (DataTableTypeConverter))]
    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates the table this DataView uses to get data.")]
#endif
    [DefaultValue (null)]
    [RefreshProperties (RefreshProperties.All)]
    public DataTable Table {
      get { return dataTable; }
      set {
        if (value == dataTable)
          return;

        if (isInitPhase) {
          initTable = value;
          return;
        }

        if (value != null && value.TableName.Equals(string.Empty)) {
          throw new DataException("Cannot bind to DataTable with no name.");
        }

        if (dataTable != null)
          UnregisterEventHandlers ();

        dataTable = value;

        if (dataTable != null) {
          RegisterEventHandlers ();
          OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged, 0, 0));
          sort = string.Empty;
          rowFilter = string.Empty;
          if (!inEndInit) {
            UpdateIndex (true);
            OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
          }
        }
      }
    }

    public virtual DataRowView AddNew ()
    {
      if (!IsOpen)
        throw new DataException ("DataView is not open.");
      if (!AllowNew)
        throw new DataException ("Cannot call AddNew on a DataView where AllowNew is false.");

      if (_lastAdded != null)
        // FIXME : finish last added
        CompleteLastAdded (true);

      _lastAdded = dataTable.NewRow ();
      UpdateIndex (true);
      OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, Count - 1, -1));

      return this [Count - 1];
    }

    internal void CompleteLastAdded (bool add)
    {
      DataRow dr = _lastAdded;

      if (add) {
        try {
          dataTable.Rows.Add (_lastAdded);
          //OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, Count - 1, -1));
          _lastAdded = null;
          UpdateIndex ();
        } catch (Exception) {
          _lastAdded = dr;
          throw;
        }
      } else {
        _lastAdded.CancelEdit ();
        _lastAdded = null;
        UpdateIndex ();
        OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, Count, -1));
      }
    }

    public void BeginInit ()
    {
      initTable = Table;
      initApplyDefaultSort = ApplyDefaultSort;
      initSort = Sort;
      initRowFilter = RowFilter;
      initRowState = RowStateFilter;

      isInitPhase = true;
      DataViewInitialized (false);
    }

    partial void DataViewInitialized (bool value);

    public void CopyTo (Array array, int index)
    {
      if (index + rowCache.Length > array.Length)
        throw new IndexOutOfRangeException ();

      int row = 0;
      for (; row < rowCache.Length && row < array.Length; row++)
        array.SetValue (rowCache [row], index + row);
    }

    public void Delete (int index)
    {
      if (!IsOpen)
        throw new DataException ("DataView is not open.");

      if (_lastAdded != null && index == Count) {
        CompleteLastAdded (false);
        return;
      }

      if (!AllowDelete)
        throw new DataException ("Cannot delete on a DataSource where AllowDelete is false.");

      if (index > rowCache.Length)
        throw new IndexOutOfRangeException ("There is no row at position: " + index + ".");
      DataRowView row = rowCache [index];
      row.Row.Delete ();
    }

    public void EndInit ()
    {
      isInitPhase = false;

      inEndInit = true;

      Table = initTable;
      ApplyDefaultSort = initApplyDefaultSort;
      Sort = initSort;
      RowFilter = initRowFilter;
      RowStateFilter = initRowState;

      inEndInit = false;

      UpdateIndex (true);

      DataViewInitialized (true);
    }

    public int Find (object key)
    {
      object [] keys = new object[] { key };
      return Find (keys);
    }

    public int Find (object [] key)
    {
      if (sort == null || sort.Length == 0)
        throw new ArgumentException ("Find finds a row based on a Sort order, and no Sort order is specified");

      if (Index == null)
        UpdateIndex (true);

      int index = -1;
      try {
        index = Index.FindIndex (key);
      } catch (FormatException) {
        // suppress exception
      } catch (InvalidCastException) {
        // suppress exception
      }
      return index;
    }

    public DataRowView [] FindRows (object key)
    {
      return FindRows (new object[] {key});
    }

    public DataRowView [] FindRows (object [] key)
    {
      if (sort == null || sort.Length == 0)
        throw new ArgumentException ("Find finds a row based on a Sort order, and no Sort order is specified");

      if (Index == null)
        UpdateIndex (true);

      int [] indexes = Index.FindAllIndexes (key);

      DataRowView[] rowViewArr = new DataRowView [indexes.Length];
      for (int r = 0; r < indexes.Length; r++)
        rowViewArr [r] = rowCache [indexes[r]];
      return rowViewArr;
    }

    public IEnumerator GetEnumerator ()
    {
      DataRowView[] dataRowViews = new DataRowView [Count];
      CopyTo (dataRowViews, 0);
      return dataRowViews.GetEnumerator ();
    }

    [DataCategory ("Data")]
#if !NET_2_0
    [DataSysDescription ("Indicates that the data returned by this DataView has somehow changed.")]
#endif
    public event ListChangedEventHandler ListChanged;

    [Browsable (false)]
#if !NET_2_0
    [DataSysDescription ("Indicates whether the view is open.  ")]
#endif
    protected bool IsOpen {
      get { return isOpen; }
    }

    internal Index Index {
      get { return _index; }
      set {
        if (_index != null) {
          _index.RemoveRef ();
          Table.DropIndex (_index);
        }

        _index = value;

        if (_index != null)
          _index.AddRef ();
      }
    }

    protected void Close ()
    {
      if (dataTable != null)
        UnregisterEventHandlers ();
      Index = null;
      rowCache = new DataRowView [0];
      isOpen = false;
    }

    protected override void Dispose (bool disposing)
    {
      if (disposing)
        Close ();

      base.Dispose (disposing);
    }

    protected virtual void IndexListChanged (object sender, ListChangedEventArgs e)
    {
    }

    protected virtual void OnListChanged (ListChangedEventArgs e)
    {
      // Yes, under MS.NET, when it is overriden, the
      // events are not fired (even if it is essential
      // to internal processing).
      try {
        if (ListChanged != null)
          ListChanged (this, e);
      } catch {
      }
    }

    internal void ChangedList (ListChangedType listChangedType, int newIndex,int oldIndex)
    {
      ListChangedEventArgs e = new ListChangedEventArgs (listChangedType,newIndex,oldIndex);
      OnListChanged (e);
    }

    protected void Open ()
    {
      // I wonder if this comment is still valid, but keep
      // in the meantime.

      // FIXME: create the initial index cache to the DataTable, and
      //        only refresh the index when the DataTable
      //        has changes via column, row, or constraint
      //        changed events. the index cache is generally
      //        a DataViewRow array that points to the actual
      //        DataRows in the this DataTable's DataRowCollection;
      //        this index is really a cache that gets
      //        created during Open(), gets Updated
      //        when various properties of this view
      //        changes, gets Updated when this DataTable's
      //        row, column, or constraint collections have changed.
      //        I'm not sure what else.
      //        The data view will know one of the DataTable's
      //        collections have changed via one of
      //        its changed events.
      //        Otherwise, if getting a/the DataRowView(s),
      //        Count, or other properties, then just use the
      //        index cache.
      //    dataTable.ColumnChanged  += new DataColumnChangeEventHandler(OnColumnChanged);

      UpdateIndex (true);
      if (dataTable != null)
        RegisterEventHandlers ();
      isOpen = true;
    }

    private void RegisterEventHandlers ()
    {
      //dataTable.ColumnChanging += new DataColumnChangeEventHandler(OnColumnChanging);
      dataTable.ColumnChanged  += new DataColumnChangeEventHandler(OnColumnChanged);
      dataTable.RowChanged     += new DataRowChangeEventHandler(OnRowChanged);
      //dataTable.RowDeleting    += new DataRowChangeEventHandler(OnRowDeleting);
      dataTable.RowDeleted     += new DataRowChangeEventHandler(OnRowDeleted);
      dataTable.Columns.CollectionChanged += new CollectionChangeEventHandler(ColumnCollectionChanged);
      dataTable.Columns.CollectionMetaDataChanged += new CollectionChangeEventHandler(ColumnCollectionChanged);
      dataTable.Constraints.CollectionChanged += new CollectionChangeEventHandler(OnConstraintCollectionChanged);
      dataTable.ChildRelations.CollectionChanged += new CollectionChangeEventHandler(OnRelationCollectionChanged);
      dataTable.ParentRelations.CollectionChanged += new CollectionChangeEventHandler(OnRelationCollectionChanged);

      dataTable.Rows.ListChanged += new ListChangedEventHandler (OnRowCollectionChanged);
    }

    private void OnRowCollectionChanged (object sender, ListChangedEventArgs args)
    {
      if (args.ListChangedType == ListChangedType.Reset) {
        rowCache = new DataRowView [0];
        UpdateIndex (true);
        OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1 ));
      }
    }

    private void UnregisterEventHandlers ()
    {
//      dataTable.ColumnChanging -= new DataColumnChangeEventHandler(OnColumnChanging);
      dataTable.ColumnChanged  -= new DataColumnChangeEventHandler(OnColumnChanged);
      dataTable.RowChanged     -= new DataRowChangeEventHandler(OnRowChanged);
//      dataTable.RowDeleting    -= new DataRowChangeEventHandler(OnRowDeleting);
      dataTable.RowDeleted     -= new DataRowChangeEventHandler(OnRowDeleted);
      dataTable.Columns.CollectionChanged -= new CollectionChangeEventHandler(ColumnCollectionChanged);
      dataTable.Columns.CollectionMetaDataChanged -= new CollectionChangeEventHandler(ColumnCollectionChanged);
      dataTable.Constraints.CollectionChanged -= new CollectionChangeEventHandler(OnConstraintCollectionChanged);
      dataTable.ChildRelations.CollectionChanged -= new CollectionChangeEventHandler(OnRelationCollectionChanged);
      dataTable.ParentRelations.CollectionChanged -= new CollectionChangeEventHandler(OnRelationCollectionChanged);

      dataTable.Rows.ListChanged -= new ListChangedEventHandler (OnRowCollectionChanged);
    }

    // These index storing and rowView preservation must be done
    // before the actual row value is changed; thus we can't use
    // RowChanging which accepts "already modified" DataRow.

    private void OnColumnChanged (object sender, DataColumnChangeEventArgs args)
    {  /* not used */
      //UpdateIndex(true);
    }

    private void OnRowChanged (object sender, DataRowChangeEventArgs args)
    {
      int oldIndex,newIndex;
      oldIndex = newIndex = -1;
      oldIndex = IndexOf (args.Row);
      UpdateIndex (true);
      newIndex = IndexOf (args.Row);

      /* ItemAdded */
      if (args.Action == DataRowAction.Add && oldIndex != newIndex)
        OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, newIndex, -1));

      /* ItemChanged or ItemDeleted */
      if (args.Action == DataRowAction.Change) {
        if (oldIndex != -1 && oldIndex == newIndex)
          OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, newIndex, -1));
        else if (oldIndex != newIndex) {
          if (newIndex < 0)
            OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, newIndex, oldIndex));
          else
            OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, newIndex, oldIndex));
        }
      }
      
      /* Rollback - ItemAdded or ItemDeleted */
      if (args.Action == DataRowAction.Rollback) {
        if (oldIndex < 0 && newIndex > -1)
          OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, newIndex, -1));
        else if (oldIndex > -1 && newIndex < 0)
          OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, newIndex, oldIndex));
        else if (oldIndex != -1 && oldIndex == newIndex)
          OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, newIndex, -1));
      }
    }

    private void OnRowDeleted (object sender, DataRowChangeEventArgs args)
    {
      /* ItemDeleted */
      int newIndex, oldCount;
      oldCount = Count;
      newIndex = IndexOf (args.Row);
      UpdateIndex (true);
      /* Fire ListChanged only when the RowFilter is affected */
      if (oldCount != Count)
        OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, newIndex, -1));
    }

    protected virtual void ColumnCollectionChanged (object sender, CollectionChangeEventArgs e)
    {
      // UpdateIndex() is not invoked here (even if the sort
      // column is being removed).

      // PropertyDescriptor Add
      if (e.Action == CollectionChangeAction.Add)
        OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorAdded, 0, 0));

      // PropertyDescriptor Removed
      if (e.Action == CollectionChangeAction.Remove)
        OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorDeleted, 0, 0));

      // PropertyDescriptor Changed
      if (e.Action == CollectionChangeAction.Refresh)
        OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged, 0, 0));
    }

    private void OnConstraintCollectionChanged (object sender, CollectionChangeEventArgs args)
    {
      //  The Sort variable is set to the UniqueConstraint column.
      //  if ApplyDefault Sort is true and Sort is null or is not set Explicitly

      // FIXME: The interal cache may change as result of change in Constraint collection
      // one such scenerio is taken care.
      // There may be more. I dont know what else can be done.
      /* useDefaultSort is set to false when Sort is set explicitly */
      if (args.Action == CollectionChangeAction.Add && args.Element is UniqueConstraint) {
        if (ApplyDefaultSort && useDefaultSort)
          PopulateDefaultSort ((UniqueConstraint) args.Element);
      }
      // UpdateIndex() is not invoked here.
    }

    private void OnRelationCollectionChanged (object sender, CollectionChangeEventArgs args)
    {
      /* PropertyDescriptor Add */
      if (args.Action == CollectionChangeAction.Add)
        OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorAdded,0,0));

      /* PropertyDescriptor Removed */
      if (args.Action == CollectionChangeAction.Remove)
        OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorDeleted,0,0));

      /* FIXME: PropertyDescriptor Changed ???*/
      if (args.Action == CollectionChangeAction.Refresh)
        OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged,0,0));
    }

    // internal use by Mono
    protected void Reset ()
    {
      // TODO: what really happens?
      Close ();
      rowCache = new DataRowView [0];
      Open ();
      OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1 ));
    }

    protected void UpdateIndex ()
    {
      UpdateIndex (false);
    }

    // This is method is internal to
    // the Mono implementation of DataView; it
    // is not to be used from your code.
    //
    // Update the DataRowView array which is an index cache
    // into the DataTable's DataRowCollection.
    //
    // I assume this is what UpdateIndex is used for
    protected virtual void UpdateIndex (bool force)
    {
      if (Table == null)
        // FIXME
        return;

      if (Index == null || force) {
        sortColumns = DataTable.ParseSortString(Table, Sort, out sortOrder, false);
        Index = dataTable.GetIndex(sortColumns,sortOrder,RowStateFilter,FilterExpression,true);
      } else {
        Index.Key.RowStateFilter = RowStateFilter;
        Index.Reset();
      }

      int[] records = Index.GetAll ();

      if (records != null)
        InitDataRowViewArray (records,Index.Size);
      else
        rowCache = new DataRowView [0];
    }

    internal virtual IExpression FilterExpression {
      get { return rowFilterExpr; }
    }

    private void InitDataRowViewArray (int [] records, int size)
    {
      if (_lastAdded != null)
        rowCache = new DataRowView [size + 1];
      else
        rowCache = new DataRowView [size];

      for (int r = 0; r < size; r++)
        rowCache [r] = new DataRowView (this, Table.RecordCache [records [r]],r);

      if (_lastAdded != null)
        rowCache [size] = new DataRowView (this, _lastAdded, size);
    }

    PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor [] listAccessors)
    {
      if (dataTable == null)
        return new PropertyDescriptorCollection (new PropertyDescriptor [0]);

      // FIXME: use listAccessors somehow
      PropertyDescriptor [] descriptors =
        new PropertyDescriptor [dataTable.Columns.Count + dataTable.ChildRelations.Count];

      int d = 0;
      for (int col = 0; col < dataTable.Columns.Count; col ++) {
        DataColumn dataColumn = dataTable.Columns[col];
        DataColumnPropertyDescriptor descriptor;

        descriptor = new DataColumnPropertyDescriptor (dataColumn.ColumnName, col, null);
        descriptor.SetComponentType (typeof (System.Data.DataRowView));
        descriptor.SetPropertyType (dataColumn.DataType);
        descriptor.SetReadOnly (dataColumn.ReadOnly);
        descriptor.SetBrowsable (dataColumn.ColumnMapping != MappingType.Hidden);
        descriptors [d++] = descriptor;
      }
      for (int rel = 0; rel < dataTable.ChildRelations.Count; rel ++) {
        DataRelation dataRelation = dataTable.ChildRelations [rel];
        DataRelationPropertyDescriptor descriptor;

        descriptor = new DataRelationPropertyDescriptor (dataRelation);
        descriptors [d++] = descriptor;
      }

      return new PropertyDescriptorCollection (descriptors);
    }


    private int IndexOf (DataRow dr)
    {
      for (int i=0; i < rowCache.Length; i++)
        if (dr.Equals (rowCache [i].Row))
        return i;
      return -1;
    }

    private void PopulateDefaultSort ()
    {
      sort = string.Empty;
      foreach (Constraint c in dataTable.Constraints) {
        if (c is UniqueConstraint) {
          PopulateDefaultSort ((UniqueConstraint) c);
          break;
        }
      }
    }

    private void PopulateDefaultSort (UniqueConstraint uc)
    {
      if (isInitPhase)
        return;

      DataColumn [] columns = uc.Columns;
      if (columns.Length == 0) {
        sort = String.Empty;
        return;
      }

      StringBuilder builder = new StringBuilder ();
      builder.Append (columns[0].ColumnName);
      for (int i = 1; i < columns.Length; i++) {
        builder.Append (", ");
        builder.Append (columns [i].ColumnName);
      }
      sort = builder.ToString ();
    }

    internal DataView CreateChildView (DataRelation relation, int index)
    {
      if (relation == null || relation.ParentTable != Table)
        throw new ArgumentException("The relation is not parented to the table to which this DataView points.");

      int record = GetRecord (index);
      object[] keyValues = new object [relation.ParentColumns.Length];
      for (int i = 0; i < relation.ParentColumns.Length; i++)
        keyValues [i] = relation.ParentColumns [i] [record];

      return new RelatedDataView (relation.ChildColumns, keyValues);
    }

    private int GetRecord (int index)
    {
      if (index < 0 || index >= Count)
        throw new IndexOutOfRangeException(String.Format("There is no row at position {0}.", index));

      return (index == Index.Size) ?
        _lastAdded.IndexFromVersion (DataRowVersion.Default) :
        Index.IndexToRecord (index);
    }

    internal DataRowVersion GetRowVersion (int index)
    {
      int record = GetRecord (index);
      return Table.RecordCache [record].VersionFromIndex (record);
    }
  }

  partial class DataView : ITypedList {
    string ITypedList.GetListName (PropertyDescriptor [] listAccessors)
    {
      if (dataTable != null)
        return dataTable.TableName;
      return string.Empty;
    }
  }

  partial class DataView : ICollection {
    bool ICollection.IsSynchronized {
      get { return false; }
    }

    object ICollection.SyncRoot {
      get { return this; }
    }
  }

  partial class DataView : IList {
    bool IList.IsFixedSize {
      get { return false; }
    }

    bool IList.IsReadOnly {
      get { return false; }
    }

    object IList.this [int recordIndex] {
      get { return this [recordIndex]; }
      [MonoTODO]
      set { throw new InvalidOperationException (); }
    }

    int IList.Add (object value)
    {
      throw new ArgumentException ("Cannot add external objects to this list.");
    }

    void IList.Clear ()
    {
      throw new ArgumentException ("Cannot clear this list.");
    }

    bool IList.Contains (object value)
    {
      DataRowView drv = value as DataRowView;
      if (drv == null)
        return false;

      return drv.DataView == this;
    }

    int IList.IndexOf (object value)
    {
      DataRowView drv = value as DataRowView;
      if (drv != null && drv.DataView == this)
        return drv.Index;
      return -1;
    }

    void IList.Insert (int index,object value)
    {
      throw new ArgumentException ("Cannot insert external objects to this list.");
    }

    void IList.Remove (object value)
    {
      DataRowView drv = value as DataRowView;
      if (drv != null && drv.DataView == this)
        ((IList) this).RemoveAt (drv.Index);

      throw new ArgumentException ("Cannot remove external objects to this list.");
    }

    void IList.RemoveAt (int index)
    {
      Delete (index);
    }
  }

  partial class DataView : IBindingList {
    [MonoTODO]
    void IBindingList.AddIndex (PropertyDescriptor property)
    {
      throw new NotImplementedException ();
    }

    object IBindingList.AddNew ()
    {
      return this.AddNew ();
    }

    void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)
    {
      if (!(property is DataColumnPropertyDescriptor))
        throw new ArgumentException ("Dataview accepts only DataColumnPropertyDescriptors", "property");
      sortProperty = property;
      string sort = String.Format ("[{0}]" , property.Name);
      if (direction == ListSortDirection.Descending)
        sort += " DESC";
      this.Sort = sort;
    }

    int IBindingList.Find (PropertyDescriptor property, object key)
    {
      DataColumn dc = Table.Columns [property.Name];
      Index index = Table.FindIndex (new DataColumn [] {dc}, sortOrder, RowStateFilter, FilterExpression);
      if (index == null)
        index = new Index (new Key (Table, new DataColumn [] {dc}, sortOrder, RowStateFilter, FilterExpression));

      return index.FindIndex (new object [] {key});
    }

    [MonoTODO]
    void IBindingList.RemoveIndex (PropertyDescriptor property)
    {
      throw new NotImplementedException ();
    }

    void IBindingList.RemoveSort ()
    {
      sortProperty = null;
      this.Sort = String.Empty;
    }

    bool IBindingList.AllowEdit {
      get { return AllowEdit; }
    }

    bool IBindingList.AllowNew {
      get { return AllowNew; }
    }

    bool IBindingList.AllowRemove {
      [MonoTODO]
      get { return AllowDelete; }
    }

    bool IBindingList.IsSorted {
      get { return (Sort != null && Sort.Length != 0); }
    }

    ListSortDirection IBindingList.SortDirection {
      get {
        if (sortOrder != null && sortOrder.Length > 0)
          return sortOrder [0];
        return ListSortDirection.Ascending;
      }
    }

    PropertyDescriptor IBindingList.SortProperty {
      get {
        if (sortProperty == null && sortColumns != null && sortColumns.Length > 0) {
          // return property from Sort String
          PropertyDescriptorCollection properties = ((ITypedList)this).GetItemProperties (null);
          return properties.Find (sortColumns [0].ColumnName, false);
        }
        return sortProperty;
      }
    }

    bool IBindingList.SupportsChangeNotification {
      get { return true; }
    }

    bool IBindingList.SupportsSearching {
      get { return true; }
    }

    bool IBindingList.SupportsSorting {
      get { return true; }
    }
  }

#if NET_2_0
  partial class DataView : IBindingListView {
    string IBindingListView.Filter {
      get { return ((DataView) this).RowFilter; }
      set { ((DataView) this).RowFilter = value; }
    }

    ListSortDescriptionCollection IBindingListView.SortDescriptions {
      get {
        ListSortDescriptionCollection col = new ListSortDescriptionCollection ();
        for (int i = 0; i < sortColumns.Length; ++i) {
          ListSortDescription ldesc = new ListSortDescription (
                    new DataColumnPropertyDescriptor (sortColumns [i]),
                    sortOrder [i]);
          ((IList) col).Add (ldesc);
        }
        return col;
      }
    }

    bool IBindingListView.SupportsAdvancedSorting {
      get { return true; }
    }

    bool IBindingListView.SupportsFiltering {
      get { return true; }
    }

    [MonoTODO]
    void IBindingListView.ApplySort (ListSortDescriptionCollection sorts)
    {
      StringBuilder sb = new StringBuilder ();
      foreach (ListSortDescription ldesc in sorts)
        sb.AppendFormat ("[{0}]{1},", ldesc.PropertyDescriptor.Name,
          (ldesc.SortDirection == ListSortDirection.Descending ? " DESC" : string.Empty));
      this.Sort = sb.ToString (0, sb.Length-1);
    }

    void IBindingListView.RemoveFilter ()
    {
      ((IBindingListView) this).Filter = string.Empty;
    }
  }

  partial class DataView : ISupportInitializeNotification {
    private bool dataViewInitialized = true;

    [Browsable (false)]
    public bool IsInitialized {
      get { return dataViewInitialized; }
    }

    public event EventHandler Initialized;

    partial void DataViewInitialized (bool value)
    {
      dataViewInitialized = value;
      if (value)
        OnDataViewInitialized (new EventArgs ());
    }

    private void OnDataViewInitialized (EventArgs e)
    {
      if (null != Initialized)
        Initialized (this, e);
    }
  }

  partial class DataView {
    public virtual bool Equals (DataView dv)
    {
      if (this == dv)
        return true;
      if (!(this.Table == dv.Table && this.Sort == dv.Sort &&
        this.RowFilter == dv.RowFilter &&
        this.RowStateFilter == dv.RowStateFilter &&
        this.AllowEdit == dv.AllowEdit &&
        this.AllowNew == dv.AllowNew &&
        this.AllowDelete == dv.AllowDelete &&
        this.Count == dv.Count))
        return false;

      for (int i = 0; i < Count; ++i)
        if (!this [i].Equals (dv [i]))
          return false;
      return true;
    }
    public DataTable ToTable ()
    {
      return this.ToTable (Table.TableName, false, new string[] {});
    }

    public DataTable ToTable (string tableName)
    {
      return this.ToTable (tableName, false, new string[] {});
    }

    public DataTable ToTable (bool isDistinct, params string[] columnNames)
    {
      return this.ToTable (Table.TableName, isDistinct, columnNames);
    }

    public DataTable ToTable (string tablename, bool isDistinct, params string[] columnNames)
    {
      if (columnNames == null)
        throw new ArgumentNullException ("columnNames", "'columnNames' argument cannot be null.");

      DataTable newTable = new DataTable (tablename);

      DataColumn[] columns;
      ListSortDirection[] sortDirection = null;
      if (columnNames.Length > 0) {
        columns = new DataColumn [columnNames.Length];
        for (int i=0; i < columnNames.Length; ++i)
          columns [i] = Table.Columns [columnNames [i]];

        if (sortColumns != null) {
          sortDirection = new ListSortDirection [columnNames.Length];
          for (int i=0; i < columnNames.Length; ++i) {
            sortDirection [i] = ListSortDirection.Ascending;
            for (int j = 0; j < sortColumns.Length; ++j) {
              if (sortColumns [j] != columns [i])
                continue;
              sortDirection [i] = sortOrder [j];
            }
          }
        }
      } else {
        columns = (DataColumn[]) Table.Columns.ToArray (typeof (DataColumn));
        sortDirection = sortOrder;
      }

      ArrayList expressionCols = new ArrayList ();
      for (int i = 0; i < columns.Length; ++i) {
        DataColumn col = columns [i].Clone ();
        if (col.Expression != String.Empty) {
          col.Expression = string.Empty;
          expressionCols.Add (col);
        }
        if (col.ReadOnly)
          col.ReadOnly = false;
        newTable.Columns.Add (col);
      }

      DataRow [] rows;

      // Get the index from index collection of the data table.
      Index index = null;
      if (sort != string.Empty)
        index = Table.GetIndex(sortColumns,sortOrder,RowStateFilter,FilterExpression,true);
      else
        index = new Index (new Key(Table, columns, sortDirection, RowStateFilter, rowFilterExpr));
      
      if (isDistinct)
        rows = index.GetDistinctRows ();
      else
        rows = index.GetAllRows ();

      foreach (DataRow row in rows) {
        DataRow newRow = newTable.NewNotInitializedRow ();
        newTable.Rows.AddInternal (newRow);
        newRow.Original = -1;
        if (row.HasVersion (DataRowVersion.Current))
          newRow.Current = newTable.RecordCache.CopyRecord (Table, row.Current, -1);
        else if (row.HasVersion (DataRowVersion.Original))
          newRow.Current = newTable.RecordCache.CopyRecord (Table, row.Original, -1);

        foreach (DataColumn col in expressionCols)
          newRow [col] = row [col.ColumnName];
        newRow.Original = -1;
      }
      return newTable;
    }
  }
#endif
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.