// // System.Data.DataColumnCollection.cs // // Author: // Christopher Podurgiel (cpodurgiel@msn.com) // Stuart Caborn // Tim Coleman (tim@timcoleman.com) // // (C) Chris Podurgiel // Copyright (C) Tim Coleman, 2002 // Copyright (C) Daniel Morgan, 2003 // using System; using System.Collections; using System.ComponentModel; namespace System.Data { [DefaultEvent ("CollectionChanged")] public class DataColumnCollection : InternalDataCollectionBase { // The defaultNameIndex is used to create a default name for a column if one wasn't given. private int defaultNameIndex; //table should be the DataTable this DataColumnCollection belongs to. private DataTable parentTable = null; // Internal Constructor. This Class can only be created from other classes in this assembly. internal DataColumnCollection(DataTable table):base() { defaultNameIndex = 1; parentTable = table; } /// /// Gets the DataColumn from the collection at the specified index. /// public virtual DataColumn this[int index] { get { return (DataColumn) base.List[index]; } } /// /// Gets the DataColumn from the collection with the specified name. /// public virtual DataColumn this[string name] { get { foreach (DataColumn column in base.List) { if (column.ColumnName == name) { return column; } } return null; } } /// /// Gets a list of the DataColumnCollection items. /// protected override ArrayList List { get { return base.List; } } //Add Logic // //Changing Event //DefaultValue set and AutoInc set check //?Validate Expression?? //Name check and creation //Set Table //Check Unique if true then add a unique constraint //?Notify Rows of new column ? //Add to collection //Changed Event /// /// Creates and adds a DataColumn object to the DataColumnCollection. /// /// public virtual DataColumn Add() { //FIXME: string defaultName = GetNextDefaultColumnName (); DataColumn column = new DataColumn (defaultName); CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this); column.SetTable(parentTable); base.List.Add(column); OnCollectionChanged(e); return column; } private string GetNextDefaultColumnName () { string defColumnName = "Column" + defaultNameIndex.ToString(); defaultNameIndex++; return defColumnName; } /// /// Creates and adds the specified DataColumn object to the DataColumnCollection. /// /// The DataColumn to add. [MonoTODO] public void Add(DataColumn column) { if(column.ColumnName.Equals(String.Empty)) { column.ColumnName = GetNextDefaultColumnName (); } //FIXME: if(Contains(column.ColumnName)) { throw new DuplicateNameException("A column named " + column.ColumnName + " already belongs to this DataTable."); } else { CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this); column.SetTable( parentTable); int ordinal = base.List.Add(column); column.SetOrdinal (ordinal); //add constraints if neccesary if(column.Unique) { UniqueConstraint uc = new UniqueConstraint(column); parentTable.Constraints.Add(uc); } //TODO: add missing constraints. i.e. Primary/Foreign keys OnCollectionChanged(e); return; } } /// /// Creates and adds a DataColumn object with the specified name to the DataColumnCollection. /// /// The name of the column. /// The newly created DataColumn. public virtual DataColumn Add(string columnName) { //FIXME: this wont work. If the user decides to add a column named //"ColumnXX" where XX is a number these two will conflict. if (columnName == null || columnName == String.Empty) { columnName = GetNextDefaultColumnName (); } if(Contains(columnName)) { throw new DuplicateNameException("A column named " + columnName + " already belongs to this DataTable."); } else { DataColumn column = new DataColumn(columnName); CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this); column.SetTable(parentTable); int ordinal = base.List.Add(column); column.SetOrdinal( ordinal ); OnCollectionChanged(e); return column; } } /// /// Creates and adds a DataColumn object with the specified name and type to the DataColumnCollection. /// /// The ColumnName to use when cretaing the column. /// The DataType of the new column. /// The newly created DataColumn. public virtual DataColumn Add(string columnName, Type type) { if (columnName == null || columnName == "") { //FIXME: this wont work. If the user decides to add a column named //"ColumnXX" where XX is a number these two will conflict. columnName = GetNextDefaultColumnName (); } if(Contains(columnName)) { throw new DuplicateNameException("A column named " + columnName + " already belongs to this DataTable."); } else { DataColumn column = new DataColumn(columnName, type); CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this); column.SetTable(parentTable); int ordinal = base.List.Add(column); column.SetOrdinal( ordinal ); OnCollectionChanged(e); return column; } } /// /// Creates and adds a DataColumn object with the specified name, type, and expression to the DataColumnCollection. /// /// The name to use when creating the column. /// The DataType of the new column. /// The expression to assign to the Expression property. /// The newly created DataColumn. public virtual DataColumn Add(string columnName, Type type, string expression) { //FIXME: See Add Logic if (columnName == null || columnName == "") { columnName = GetNextDefaultColumnName (); } if(Contains(columnName)) { throw new DuplicateNameException("A column named " + columnName + " already belongs to this DataTable."); } else { DataColumn column = new DataColumn(columnName, type, expression); CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this); column.SetTable(parentTable); int ordinal = base.List.Add(column); column.SetOrdinal( ordinal ); OnCollectionChanged(e); return column; } } /// /// Copies the elements of the specified DataColumn array to the end of the collection. /// /// The array of DataColumn objects to add to the collection. public void AddRange(DataColumn[] columns) { foreach (DataColumn column in columns) { Add(column); } return; } /// /// Checks whether a given column can be removed from the collection. /// /// A DataColumn in the collection. /// true if the column can be removed; otherwise, false. public bool CanRemove(DataColumn column) { //Check that the column does not have a null reference. if (column == null) { return false; } //Check that the column is part of this collection. if (!Contains(column.ColumnName)) { return false; } //Check if this column is part of a relationship. (this could probably be written better) foreach (DataRelation childRelation in parentTable.ChildRelations) { foreach (DataColumn childColumn in childRelation.ChildColumns) { if (childColumn == column) { return false; } } foreach (DataColumn parentColumn in childRelation.ParentColumns) { if (parentColumn == column) { return false; } } } //Check if this column is part of a relationship. (this could probably be written better) foreach (DataRelation parentRelation in parentTable.ParentRelations) { foreach (DataColumn childColumn in parentRelation.ChildColumns) { if (childColumn == column) { return false; } } foreach (DataColumn parentColumn in parentRelation.ParentColumns) { if (parentColumn == column) { return false; } } } //Check if another column's expression depends on this column. foreach (DataColumn dataColumn in List) { if (dataColumn.Expression.ToString().IndexOf(column.ColumnName) > 0) { return false; } } //TODO: check constraints return true; } /// /// Clears the collection of any columns. /// public void Clear() { CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this); base.List.Clear(); OnCollectionChanged(e); return; } /// /// Checks whether the collection contains a column with the specified name. /// /// The ColumnName of the column to check for. /// true if a column exists with this name; otherwise, false. public bool Contains(string name) { return (IndexOf(name) != -1); } /// /// Gets the index of a column specified by name. /// /// The name of the column to return. /// The index of the column specified by column if it is found; otherwise, -1. public virtual int IndexOf(DataColumn column) { return base.List.IndexOf(column); } /// /// Gets the index of the column with the given name (the name is not case sensitive). /// /// The name of the column to find. /// The zero-based index of the column with the specified name, or -1 if the column doesn't exist in the collection. public int IndexOf(string columnName) { DataColumn column = this[columnName]; if (column != null) { return IndexOf(column); } else { return -1; } } /// /// Raises the OnCollectionChanged event. /// /// A CollectionChangeEventArgs that contains the event data. protected virtual void OnCollectionChanged(CollectionChangeEventArgs ccevent) { if (CollectionChanged != null) { CollectionChanged(this, ccevent); } } /// /// Raises the OnCollectionChanging event. /// /// A CollectionChangeEventArgs that contains the event data. protected internal virtual void OnCollectionChanging(CollectionChangeEventArgs ccevent) { if (CollectionChanged != null) { //FIXME: this is not right //CollectionChanged(this, ccevent); throw new NotImplementedException(); } } /// /// Removes the specified DataColumn object from the collection. /// /// The DataColumn to remove. public void Remove(DataColumn column) { //TODO: can remove first with exceptions //and OnChanging Event CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this); int ordinal = column.Ordinal; base.List.Remove(column); //Update the ordinals for( int i = ordinal ; i < this.Count ; i ++ ) { this[i].SetOrdinal( i ); } OnCollectionChanged(e); return; } /// /// Removes the DataColumn object with the specified name from the collection. /// /// The name of the column to remove. public void Remove(string name) { DataColumn column = this[name]; Remove( column ); } /// /// Removes the column at the specified index from the collection. /// /// The index of the column to remove. public void RemoveAt(int index) { DataColumn column = this[index]; Remove( column ); } /// /// Occurs when the columns collection changes, either by adding or removing a column. /// public event CollectionChangeEventHandler CollectionChanged; } }