PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Data/System.Data/DataColumnCollection.cs

https://bitbucket.org/danipen/mono
C# | 735 lines | 464 code | 95 blank | 176 comment | 134 complexity | 293eab28611a87789dd5b618a246f2d0 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // System.Data.DataColumnCollection.cs
  3. //
  4. // Author:
  5. // Christopher Podurgiel (cpodurgiel@msn.com)
  6. // Stuart Caborn <stuart.caborn@virgin.net>
  7. // Tim Coleman (tim@timcoleman.com)
  8. //
  9. // (C) Chris Podurgiel
  10. // Copyright (C) Tim Coleman, 2002
  11. // Copyright (C) Daniel Morgan, 2003
  12. //
  13. //
  14. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  15. //
  16. // Permission is hereby granted, free of charge, to any person obtaining
  17. // a copy of this software and associated documentation files (the
  18. // "Software"), to deal in the Software without restriction, including
  19. // without limitation the rights to use, copy, modify, merge, publish,
  20. // distribute, sublicense, and/or sell copies of the Software, and to
  21. // permit persons to whom the Software is furnished to do so, subject to
  22. // the following conditions:
  23. //
  24. // The above copyright notice and this permission notice shall be
  25. // included in all copies or substantial portions of the Software.
  26. //
  27. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  28. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  29. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  30. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  31. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  32. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  33. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  34. //
  35. using System;
  36. using System.Text;
  37. using System.Collections;
  38. using System.ComponentModel;
  39. namespace System.Data {
  40. internal class Doublet
  41. {
  42. public Doublet (int count, string columnname)
  43. {
  44. this.count = count;
  45. this.columnNames.Add (columnname);
  46. }
  47. // Number of case insensitive column name
  48. public int count;
  49. // Array of exact column names
  50. public ArrayList columnNames = new ArrayList ();
  51. }
  52. [Editor ("Microsoft.VSDesigner.Data.Design.ColumnsCollectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
  53. "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
  54. #if !NET_2_0
  55. [Serializable]
  56. #endif
  57. [DefaultEvent ("CollectionChanged")]
  58. public
  59. #if NET_2_0
  60. sealed
  61. #endif
  62. class DataColumnCollection : InternalDataCollectionBase {
  63. //This hashtable maps between unique case insensetive column name to a doublet containing column ref and column count
  64. #if NET_2_0
  65. private Hashtable columnNameCount = new Hashtable (StringComparer.OrdinalIgnoreCase);
  66. #else
  67. private Hashtable columnNameCount = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
  68. #endif
  69. //This hashtable maps between column name to DataColumn object.
  70. private Hashtable columnFromName = new Hashtable ();
  71. //This ArrayList contains the auto-increment columns names
  72. private ArrayList autoIncrement = new ArrayList ();
  73. //This holds the next index to use for default column name.
  74. private int defaultColumnIndex = 1;
  75. //table should be the DataTable this DataColumnCollection belongs to.
  76. private DataTable parentTable = null;
  77. // Keep reference to most recent columns passed to AddRange()
  78. // so that they can be added when EndInit() is called.
  79. DataColumn [] _mostRecentColumns = null;
  80. static readonly string ColumnPrefix = "Column";
  81. // Internal Constructor. This Class can only be created from other classes in this assembly.
  82. internal DataColumnCollection (DataTable table)
  83. {
  84. parentTable = table;
  85. }
  86. /// <summary>
  87. /// Gets the DataColumn from the collection at the specified index.
  88. /// </summary>
  89. public
  90. #if !NET_2_0
  91. virtual
  92. #endif
  93. DataColumn this [int index] {
  94. get {
  95. if (index < 0 || index >= base.List.Count)
  96. throw new IndexOutOfRangeException ("Cannot find column " + index + ".");
  97. return (DataColumn) base.List [index];
  98. }
  99. }
  100. /// <summary>
  101. /// Gets the DataColumn from the collection with the specified name.
  102. /// </summary>
  103. public
  104. #if !NET_2_0
  105. virtual
  106. #endif
  107. DataColumn this [string name] {
  108. get {
  109. #if NET_2_0
  110. if (name == null)
  111. throw new ArgumentNullException ("name");
  112. #endif
  113. DataColumn dc = columnFromName [name] as DataColumn;
  114. if (dc != null)
  115. return dc;
  116. int tmp = IndexOf (name, true);
  117. return tmp == -1 ? null : (DataColumn) base.List [tmp];
  118. }
  119. }
  120. /// <summary>
  121. /// Gets a list of the DataColumnCollection items.
  122. /// </summary>
  123. protected override ArrayList List {
  124. get { return base.List; }
  125. }
  126. internal ArrayList AutoIncrmentColumns {
  127. get { return autoIncrement; }
  128. }
  129. //Add Logic
  130. //
  131. //Changing Event
  132. //DefaultValue set and AutoInc set check
  133. //?Validate Expression??
  134. //Name check and creation
  135. //Set Table
  136. //Check Unique if true then add a unique constraint
  137. //?Notify Rows of new column ?
  138. //Add to collection
  139. //Changed Event
  140. /// <summary>
  141. /// Creates and adds a DataColumn object to the DataColumnCollection.
  142. /// </summary>
  143. /// <returns></returns>
  144. public
  145. #if !NET_2_0
  146. virtual
  147. #endif
  148. DataColumn Add ()
  149. {
  150. DataColumn column = new DataColumn (null);
  151. Add (column);
  152. return column;
  153. }
  154. #if NET_2_0
  155. public void CopyTo (DataColumn [] array, int index)
  156. {
  157. CopyTo ((Array) array, index);
  158. }
  159. #endif
  160. internal void RegisterName (string name, DataColumn column)
  161. {
  162. try {
  163. columnFromName.Add (name, column);
  164. } catch (ArgumentException) {
  165. throw new DuplicateNameException ("A DataColumn named '" + name + "' already belongs to this DataTable.");
  166. }
  167. // Get existing doublet
  168. Doublet d = (Doublet) columnNameCount [name];
  169. if (d != null) {
  170. // Add reference count
  171. d.count++;
  172. // Add a new name
  173. d.columnNames.Add (name);
  174. } else {
  175. // no existing doublet
  176. // create one
  177. d = new Doublet (1, name);
  178. columnNameCount [name] = d;
  179. }
  180. #if NET_2_0
  181. if (name.Length <= ColumnPrefix.Length || !name.StartsWith (ColumnPrefix, StringComparison.Ordinal))
  182. return;
  183. #else
  184. if (name.Length <= ColumnPrefix.Length || !name.StartsWith (ColumnPrefix))
  185. return;
  186. #endif
  187. if (name == MakeName (defaultColumnIndex + 1)) {
  188. do {
  189. defaultColumnIndex++;
  190. } while (Contains (MakeName (defaultColumnIndex + 1)));
  191. }
  192. }
  193. internal void UnregisterName (string name)
  194. {
  195. if (columnFromName.Contains (name))
  196. columnFromName.Remove (name);
  197. // Get the existing doublet
  198. Doublet d = (Doublet) columnNameCount [name];
  199. if (d != null) {
  200. // decrease reference count
  201. d.count--;
  202. d.columnNames.Remove (name);
  203. // remove doublet if no more references
  204. if (d.count == 0)
  205. columnNameCount.Remove (name);
  206. }
  207. if (name.StartsWith(ColumnPrefix) && name == MakeName(defaultColumnIndex - 1)) {
  208. do {
  209. defaultColumnIndex--;
  210. } while (!Contains (MakeName (defaultColumnIndex - 1)) && defaultColumnIndex > 1);
  211. }
  212. }
  213. private string GetNextDefaultColumnName ()
  214. {
  215. string defColumnName = MakeName (defaultColumnIndex);
  216. for (int index = defaultColumnIndex + 1; Contains (defColumnName); ++index) {
  217. defColumnName = MakeName (index);
  218. defaultColumnIndex++;
  219. }
  220. defaultColumnIndex++;
  221. return defColumnName;
  222. }
  223. static readonly string[] TenColumns = { "Column0", "Column1", "Column2", "Column3", "Column4", "Column5", "Column6", "Column7", "Column8", "Column9" };
  224. static string MakeName (int index)
  225. {
  226. if (index < 10)
  227. return TenColumns [index];
  228. return String.Concat (ColumnPrefix, index.ToString());
  229. }
  230. /// <summary>
  231. /// Creates and adds the specified DataColumn object to the DataColumnCollection.
  232. /// </summary>
  233. /// <param name="column">The DataColumn to add.</param>
  234. public void Add (DataColumn column)
  235. {
  236. if (column == null)
  237. throw new ArgumentNullException ("column", "'column' argument cannot be null.");
  238. #if !NET_2_0
  239. /* in 1.1, they must do this here, as the
  240. * setting of ColumnName below causes an event
  241. * to be raised */
  242. column.PropertyChanged += new PropertyChangedEventHandler (ColumnPropertyChanged);
  243. #endif
  244. if (column.ColumnName.Length == 0) {
  245. column.ColumnName = GetNextDefaultColumnName ();
  246. }
  247. // if (Contains(column.ColumnName))
  248. // throw new DuplicateNameException("A DataColumn named '" + column.ColumnName + "' already belongs to this DataTable.");
  249. if (column.Table != null)
  250. throw new ArgumentException ("Column '" + column.ColumnName + "' already belongs to this or another DataTable.");
  251. column.SetTable (parentTable);
  252. RegisterName (column.ColumnName, column);
  253. int ordinal = base.List.Add (column);
  254. #if NET_2_0
  255. column.Ordinal = ordinal;
  256. #else
  257. column.SetOrdinal (ordinal);
  258. #endif
  259. // Check if the Column Expression is ok
  260. if (column.CompiledExpression != null)
  261. if (parentTable.Rows.Count == 0)
  262. column.CompiledExpression.Eval (parentTable.NewRow());
  263. else
  264. column.CompiledExpression.Eval (parentTable.Rows[0]);
  265. // if table already has rows we need to allocate space
  266. // in the column data container
  267. if (parentTable.Rows.Count > 0)
  268. column.DataContainer.Capacity = parentTable.RecordCache.CurrentCapacity;
  269. if (column.AutoIncrement) {
  270. DataRowCollection rows = column.Table.Rows;
  271. for (int i = 0; i < rows.Count; i++)
  272. rows [i] [ordinal] = column.AutoIncrementValue ();
  273. }
  274. if (column.AutoIncrement)
  275. autoIncrement.Add (column);
  276. #if NET_2_0
  277. column.PropertyChanged += new PropertyChangedEventHandler (ColumnPropertyChanged);
  278. #endif
  279. OnCollectionChanged (new CollectionChangeEventArgs(CollectionChangeAction.Add, column));
  280. }
  281. /// <summary>
  282. /// Creates and adds a DataColumn object with the specified name to the DataColumnCollection.
  283. /// </summary>
  284. /// <param name="columnName">The name of the column.</param>
  285. /// <returns>The newly created DataColumn.</returns>
  286. public
  287. #if !NET_2_0
  288. virtual
  289. #endif
  290. DataColumn Add (string columnName)
  291. {
  292. DataColumn column = new DataColumn (columnName);
  293. Add (column);
  294. return column;
  295. }
  296. /// <summary>
  297. /// Creates and adds a DataColumn object with the specified name and type to the DataColumnCollection.
  298. /// </summary>
  299. /// <param name="columnName">The ColumnName to use when cretaing the column.</param>
  300. /// <param name="type">The DataType of the new column.</param>
  301. /// <returns>The newly created DataColumn.</returns>
  302. public
  303. #if !NET_2_0
  304. virtual
  305. #endif
  306. DataColumn Add (string columnName, Type type)
  307. {
  308. if (columnName == null || columnName == "")
  309. columnName = GetNextDefaultColumnName ();
  310. DataColumn column = new DataColumn (columnName, type);
  311. Add (column);
  312. return column;
  313. }
  314. /// <summary>
  315. /// Creates and adds a DataColumn object with the specified name, type, and expression to the DataColumnCollection.
  316. /// </summary>
  317. /// <param name="columnName">The name to use when creating the column.</param>
  318. /// <param name="type">The DataType of the new column.</param>
  319. /// <param name="expression">The expression to assign to the Expression property.</param>
  320. /// <returns>The newly created DataColumn.</returns>
  321. public
  322. #if !NET_2_0
  323. virtual
  324. #endif
  325. DataColumn Add (string columnName, Type type, string expression)
  326. {
  327. if (columnName == null || columnName == "")
  328. columnName = GetNextDefaultColumnName ();
  329. DataColumn column = new DataColumn (columnName, type, expression);
  330. Add (column);
  331. return column;
  332. }
  333. /// <summary>
  334. /// Copies the elements of the specified DataColumn array to the end of the collection.
  335. /// </summary>
  336. /// <param name="columns">The array of DataColumn objects to add to the collection.</param>
  337. public void AddRange (DataColumn [] columns)
  338. {
  339. if (parentTable.InitInProgress){
  340. _mostRecentColumns = columns;
  341. return;
  342. }
  343. if (columns == null)
  344. return;
  345. foreach (DataColumn column in columns){
  346. if (column == null)
  347. continue;
  348. Add(column);
  349. }
  350. }
  351. private string GetColumnDependency (DataColumn column)
  352. {
  353. foreach (DataRelation rel in parentTable.ParentRelations)
  354. if (Array.IndexOf (rel.ChildColumns, column) != -1)
  355. return String.Format (" child key for relationship {0}.", rel.RelationName);
  356. foreach (DataRelation rel in parentTable.ChildRelations)
  357. if (Array.IndexOf (rel.ParentColumns, column) != -1)
  358. return String.Format (" parent key for relationship {0}.", rel.RelationName);
  359. foreach (Constraint c in parentTable.Constraints)
  360. if (c.IsColumnContained (column))
  361. return String.Format (" constraint {0} on the table {1}.",
  362. c.ConstraintName, parentTable);
  363. // check if the foreign-key constraint on any table in the dataset refers to this column.
  364. // though a forignkeyconstraint automatically creates a uniquecontrainton the parent
  365. // table and would fail above, but we still need to check, as it is legal to manually remove
  366. // the constraint on the parent table.
  367. if (parentTable.DataSet != null)
  368. foreach (DataTable table in parentTable.DataSet.Tables)
  369. foreach (Constraint c in table.Constraints)
  370. if (c is ForeignKeyConstraint && c.IsColumnContained(column))
  371. return String.Format (
  372. " constraint {0} on the table {1}.", c.ConstraintName, table.TableName);
  373. foreach (DataColumn col in this)
  374. if (col.CompiledExpression != null && col.CompiledExpression.DependsOn (column))
  375. return col.Expression;
  376. return String.Empty;
  377. }
  378. /// <summary>
  379. /// Checks whether a given column can be removed from the collection.
  380. /// </summary>
  381. /// <param name="column">A DataColumn in the collection.</param>
  382. /// <returns>true if the column can be removed; otherwise, false.</returns>
  383. public bool CanRemove (DataColumn column)
  384. {
  385. if (column == null || column.Table != parentTable || GetColumnDependency (column) != String.Empty)
  386. return false;
  387. return true;
  388. }
  389. /// <summary>
  390. /// Clears the collection of any columns.
  391. /// </summary>
  392. public void Clear ()
  393. {
  394. CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this);
  395. // its not necessary to check if each column in the collection can removed.
  396. // Can simply check, if there are any constraints/relations related to the table,
  397. // in which case, throw an exception.
  398. // Also, shudnt check for expression columns since all the columns in the table
  399. // are being removed.
  400. if (parentTable.Constraints.Count != 0 ||
  401. parentTable.ParentRelations.Count != 0 ||
  402. parentTable.ChildRelations.Count != 0)
  403. foreach (DataColumn col in this) {
  404. string s = GetColumnDependency (col);
  405. if (s != String.Empty)
  406. throw new ArgumentException ("Cannot remove this column, because it is part of the" + s);
  407. }
  408. if (parentTable.DataSet != null)
  409. foreach (DataTable table in parentTable.DataSet.Tables)
  410. foreach (Constraint c in table.Constraints) {
  411. if (!(c is ForeignKeyConstraint) ||
  412. ((ForeignKeyConstraint) c).RelatedTable != parentTable)
  413. continue;
  414. throw new ArgumentException (
  415. String.Format (
  416. "Cannot remove this column, because it is part of the constraint {0} on the table {1}",
  417. c.ConstraintName, table.TableName));
  418. }
  419. foreach (DataColumn col in this)
  420. col.ResetColumnInfo ();
  421. columnFromName.Clear ();
  422. autoIncrement.Clear ();
  423. columnNameCount.Clear ();
  424. base.List.Clear ();
  425. defaultColumnIndex = 1;
  426. OnCollectionChanged (e);
  427. }
  428. /// <summary>
  429. /// Checks whether the collection contains a column with the specified name.
  430. /// </summary>
  431. /// <param name="name">The ColumnName of the column to check for.</param>
  432. /// <returns>true if a column exists with this name; otherwise, false.</returns>
  433. public bool Contains (string name)
  434. {
  435. if (columnFromName.Contains (name))
  436. return true;
  437. return (IndexOf (name, false) != -1);
  438. }
  439. /// <summary>
  440. /// Gets the index of a column specified by name.
  441. /// </summary>
  442. /// <param name="column">The name of the column to return.</param>
  443. /// <returns>The index of the column specified by column if it is found; otherwise, -1.</returns>
  444. public
  445. #if !NET_2_0
  446. virtual
  447. #endif
  448. int IndexOf (DataColumn column)
  449. {
  450. if (column == null)
  451. return -1;
  452. return base.List.IndexOf (column);
  453. }
  454. /// <summary>
  455. /// Gets the index of the column with the given name (the name is not case sensitive).
  456. /// </summary>
  457. /// <param name="columnName">The name of the column to find.</param>
  458. /// <returns>The zero-based index of the column with the specified name, or -1 if the column doesn't exist in the collection.</returns>
  459. public int IndexOf (string columnName)
  460. {
  461. if (columnName == null)
  462. return -1;
  463. DataColumn dc = columnFromName [columnName] as DataColumn;
  464. if (dc != null)
  465. return IndexOf (dc);
  466. return IndexOf (columnName, false);
  467. }
  468. /// <summary>
  469. /// Raises the OnCollectionChanged event.
  470. /// </summary>
  471. /// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
  472. #if !NET_2_0
  473. protected virtual
  474. #else
  475. internal
  476. #endif
  477. void OnCollectionChanged (CollectionChangeEventArgs ccevent)
  478. {
  479. parentTable.ResetPropertyDescriptorsCache ();
  480. if (CollectionChanged != null)
  481. CollectionChanged (this, ccevent);
  482. }
  483. /// <summary>
  484. /// Raises the OnCollectionChanging event.
  485. /// </summary>
  486. /// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
  487. #if !NET_2_0
  488. protected internal virtual
  489. #else
  490. internal
  491. #endif
  492. void OnCollectionChanging (CollectionChangeEventArgs ccevent)
  493. {
  494. if (CollectionChanged != null) {
  495. //FIXME: this is not right
  496. //CollectionChanged(this, ccevent);
  497. throw new NotImplementedException();
  498. }
  499. }
  500. /// <summary>
  501. /// Removes the specified DataColumn object from the collection.
  502. /// </summary>
  503. /// <param name="column">The DataColumn to remove.</param>
  504. public void Remove (DataColumn column)
  505. {
  506. if (column == null)
  507. throw new ArgumentNullException ("column", "'column' argument cannot be null.");
  508. if (!Contains (column.ColumnName))
  509. throw new ArgumentException ("Cannot remove a column that doesn't belong to this table.");
  510. string dependency = GetColumnDependency (column);
  511. if (dependency != String.Empty)
  512. throw new ArgumentException ("Cannot remove this column, because it is part of " + dependency);
  513. CollectionChangeEventArgs e = new CollectionChangeEventArgs (CollectionChangeAction.Remove, column);
  514. int ordinal = column.Ordinal;
  515. UnregisterName (column.ColumnName);
  516. base.List.Remove (column);
  517. // Reset column info
  518. column.ResetColumnInfo ();
  519. //Update the ordinals
  520. for( int i = ordinal ; i < this.Count ; i ++ )
  521. #if NET_2_0
  522. this[i].Ordinal = i;
  523. #else
  524. this[i].SetOrdinal(i);
  525. #endif
  526. if (parentTable != null)
  527. parentTable.OnRemoveColumn (column);
  528. if (column.AutoIncrement)
  529. autoIncrement.Remove (column);
  530. column.PropertyChanged -= new PropertyChangedEventHandler (ColumnPropertyChanged);
  531. OnCollectionChanged (e);
  532. }
  533. /// <summary>
  534. /// Removes the DataColumn object with the specified name from the collection.
  535. /// </summary>
  536. /// <param name="name">The name of the column to remove.</param>
  537. public void Remove (string name)
  538. {
  539. DataColumn column = this [name];
  540. if (column == null)
  541. throw new ArgumentException ("Column '" + name + "' does not belong to table " + ( parentTable == null ? "" : parentTable.TableName ) + ".");
  542. Remove (column);
  543. }
  544. /// <summary>
  545. /// Removes the column at the specified index from the collection.
  546. /// </summary>
  547. /// <param name="index">The index of the column to remove.</param>
  548. public void RemoveAt (int index)
  549. {
  550. if (Count <= index)
  551. throw new IndexOutOfRangeException ("Cannot find column " + index + ".");
  552. DataColumn column = this [index];
  553. Remove (column);
  554. }
  555. // Helper AddRange() - Call this function when EndInit is called
  556. internal void PostAddRange ()
  557. {
  558. if (_mostRecentColumns == null)
  559. return;
  560. foreach (DataColumn column in _mostRecentColumns){
  561. if (column == null)
  562. continue;
  563. Add (column);
  564. }
  565. _mostRecentColumns = null;
  566. }
  567. internal void UpdateAutoIncrement (DataColumn col,bool isAutoIncrement)
  568. {
  569. if (isAutoIncrement) {
  570. if (!autoIncrement.Contains (col))
  571. autoIncrement.Add (col);
  572. } else {
  573. if (autoIncrement.Contains (col))
  574. autoIncrement.Remove (col);
  575. }
  576. }
  577. private int IndexOf (string name, bool error)
  578. {
  579. // exact case matching has already be done by the caller
  580. // Get existing doublet
  581. Doublet d = (Doublet) columnNameCount [name];
  582. if (d != null) {
  583. if (d.count == 1) {
  584. // There's only one
  585. // return index of the column from the only column name of the doublet
  586. return base.List.IndexOf (columnFromName [d.columnNames [0]]);
  587. } else if (d.count > 1 && error) {
  588. // there's more than one, exception!
  589. throw new ArgumentException ("There is no match for '" + name + "' in the same case and there are multiple matches in different case.");
  590. } else {
  591. return -1;
  592. }
  593. }
  594. return -1;
  595. }
  596. #region Events
  597. /// <summary>
  598. /// Occurs when the columns collection changes, either by adding or removing a column.
  599. /// </summary>
  600. [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
  601. public event CollectionChangeEventHandler CollectionChanged;
  602. internal event CollectionChangeEventHandler CollectionMetaDataChanged;
  603. #endregion
  604. private void OnCollectionMetaDataChanged (CollectionChangeEventArgs ccevent)
  605. {
  606. parentTable.ResetPropertyDescriptorsCache ();
  607. if (CollectionMetaDataChanged != null)
  608. CollectionMetaDataChanged (this, ccevent);
  609. }
  610. private void ColumnPropertyChanged (object sender, PropertyChangedEventArgs args)
  611. {
  612. OnCollectionMetaDataChanged (new CollectionChangeEventArgs(CollectionChangeAction.Refresh, sender));
  613. }
  614. #if NET_2_0
  615. internal void MoveColumn (int oldOrdinal, int newOrdinal)
  616. {
  617. if (newOrdinal == -1 || newOrdinal > this.Count)
  618. throw new ArgumentOutOfRangeException ("ordinal", "Ordinal '" + newOrdinal + "' exceeds the maximum number.");
  619. if (oldOrdinal == newOrdinal)
  620. return;
  621. int start = newOrdinal > oldOrdinal ? oldOrdinal : newOrdinal;
  622. int end = newOrdinal > oldOrdinal ? newOrdinal : oldOrdinal;
  623. int direction = newOrdinal > oldOrdinal ? 1 : (-1);
  624. // swap ordinals as per direction of column movement
  625. if (direction < 0) {
  626. start = start + end;
  627. end = start - end;
  628. start -= end;
  629. }
  630. DataColumn currColumn = this [start];
  631. for (int i = start; (direction>0 ? i<end : i>end); i += direction) {
  632. List [i] = List [i+direction];
  633. ((DataColumn) List [i]).Ordinal = i;
  634. }
  635. List [end] = currColumn;
  636. currColumn.Ordinal = end;
  637. }
  638. #endif
  639. }
  640. }