|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections;
using System.ComponentModel;
namespace System.Windows.Forms;
/// <summary>
/// Represents a collection of <see cref="DataGridViewCell"/> objects in the <see cref="DataGridView"/>
/// control.
/// </summary>
[ListBindable(false)]
public class DataGridViewCellCollection : BaseCollection, IList
{
private CollectionChangeEventHandler? _onCollectionChanged;
private readonly List<DataGridViewCell> _items = [];
private readonly DataGridViewRow _owner;
int IList.Add(object? value) => Add((DataGridViewCell)value!);
void IList.Clear() => Clear();
bool IList.Contains(object? value) => ((IList)_items).Contains(value);
int IList.IndexOf(object? value) => ((IList)_items).IndexOf(value);
void IList.Insert(int index, object? value) => Insert(index, (DataGridViewCell)value!);
void IList.Remove(object? value) => Remove((DataGridViewCell)value!);
void IList.RemoveAt(int index) => RemoveAt(index);
bool IList.IsFixedSize => ((IList)_items).IsFixedSize;
bool IList.IsReadOnly => ((IList)_items).IsReadOnly;
object? IList.this[int index]
{
get { return this[index]; }
set { this[index] = (DataGridViewCell)value!; }
}
void ICollection.CopyTo(Array array, int index) => ((ICollection)_items).CopyTo(array, index);
int ICollection.Count => _items.Count;
bool ICollection.IsSynchronized => ((ICollection)_items).IsSynchronized;
object ICollection.SyncRoot => ((ICollection)_items).SyncRoot;
IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();
public DataGridViewCellCollection(DataGridViewRow dataGridViewRow)
{
Debug.Assert(dataGridViewRow is not null);
_owner = dataGridViewRow;
}
protected override ArrayList List => ArrayList.Adapter(_items);
/// <summary>
/// Retrieves the DataGridViewCell with the specified index.
/// </summary>
public DataGridViewCell this[int index]
{
get => _items[index];
set
{
DataGridViewCell dataGridViewCell = value.OrThrowIfNull();
if (dataGridViewCell.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_CellAlreadyBelongsToDataGridView);
}
if (dataGridViewCell.OwningRow is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_CellAlreadyBelongsToDataGridViewRow);
}
_owner.DataGridView?.OnReplacingCell(_owner, index);
DataGridViewCell oldDataGridViewCell = _items[index];
_items[index] = dataGridViewCell;
dataGridViewCell.OwningRow = _owner;
dataGridViewCell.State = oldDataGridViewCell.State;
if (_owner.DataGridView is not null)
{
dataGridViewCell.DataGridView = _owner.DataGridView;
dataGridViewCell.OwningColumn = _owner.DataGridView.Columns[index];
_owner.DataGridView.OnReplacedCell(_owner, index);
}
oldDataGridViewCell.DataGridView = null;
oldDataGridViewCell.OwningRow = null;
oldDataGridViewCell.OwningColumn = null;
if (oldDataGridViewCell.ReadOnly)
{
oldDataGridViewCell.ReadOnlyInternal = false;
}
if (oldDataGridViewCell.Selected)
{
oldDataGridViewCell.SelectedInternal = false;
}
}
}
/// <summary>
/// Retrieves the DataGridViewCell with the specified column name.
/// </summary>
public DataGridViewCell this[string columnName]
{
get
{
DataGridViewColumn? dataGridViewColumn = null;
if (_owner.DataGridView is not null)
{
dataGridViewColumn = _owner.DataGridView.Columns[columnName];
}
if (dataGridViewColumn is null)
{
throw new ArgumentException(string.Format(SR.DataGridViewColumnCollection_ColumnNotFound, columnName), nameof(columnName));
}
return _items[dataGridViewColumn.Index];
}
set
{
DataGridViewColumn? dataGridViewColumn = null;
if (_owner.DataGridView is not null)
{
dataGridViewColumn = _owner.DataGridView.Columns[columnName];
}
if (dataGridViewColumn is null)
{
throw new ArgumentException(string.Format(SR.DataGridViewColumnCollection_ColumnNotFound, columnName), nameof(columnName));
}
this[dataGridViewColumn.Index] = value;
}
}
public event CollectionChangeEventHandler? CollectionChanged
{
add => _onCollectionChanged += value;
remove => _onCollectionChanged -= value;
}
/// <summary>
/// Adds a <see cref="DataGridViewCell"/> to this collection.
/// </summary>
public virtual int Add(DataGridViewCell dataGridViewCell)
{
if (_owner.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_OwningRowAlreadyBelongsToDataGridView);
}
if (dataGridViewCell.OwningRow is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_CellAlreadyBelongsToDataGridViewRow);
}
return AddInternal(dataGridViewCell);
}
internal int AddInternal(DataGridViewCell dataGridViewCell)
{
Debug.Assert(!dataGridViewCell.Selected);
int index = ((IList)_items).Add(dataGridViewCell);
dataGridViewCell.OwningRow = _owner;
DataGridView? dataGridView = _owner.DataGridView;
if (dataGridView is not null && dataGridView.Columns.Count > index)
{
dataGridViewCell.OwningColumn = dataGridView.Columns[index];
}
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, dataGridViewCell));
return index;
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual void AddRange(params DataGridViewCell[] dataGridViewCells)
{
ArgumentNullException.ThrowIfNull(dataGridViewCells);
if (_owner.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_OwningRowAlreadyBelongsToDataGridView);
}
foreach (DataGridViewCell dataGridViewCell in dataGridViewCells)
{
if (dataGridViewCell is null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_AtLeastOneCellIsNull);
}
if (dataGridViewCell.OwningRow is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_CellAlreadyBelongsToDataGridViewRow);
}
}
// Make sure no two cells are identical
int cellCount = dataGridViewCells.Length;
for (int cell1 = 0; cell1 < cellCount - 1; cell1++)
{
for (int cell2 = cell1 + 1; cell2 < cellCount; cell2++)
{
if (dataGridViewCells[cell1] == dataGridViewCells[cell2])
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_CannotAddIdenticalCells);
}
}
}
_items.AddRange(dataGridViewCells);
foreach (DataGridViewCell dataGridViewCell in dataGridViewCells)
{
dataGridViewCell.OwningRow = _owner;
Debug.Assert(!dataGridViewCell.Selected);
}
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, null));
}
public virtual void Clear()
{
if (_owner.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_OwningRowAlreadyBelongsToDataGridView);
}
foreach (DataGridViewCell dataGridViewCell in _items)
{
dataGridViewCell.OwningRow = null;
}
_items.Clear();
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, null));
}
public void CopyTo(DataGridViewCell[] array, int index)
{
_items.CopyTo(array, index);
}
/// <summary>
/// Checks to see if a DataGridViewCell is contained in this collection.
/// </summary>
public virtual bool Contains(DataGridViewCell dataGridViewCell)
{
int index = _items.IndexOf(dataGridViewCell);
return index != -1;
}
public int IndexOf(DataGridViewCell dataGridViewCell) => _items.IndexOf(dataGridViewCell);
public virtual void Insert(int index, DataGridViewCell dataGridViewCell)
{
if (_owner.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_OwningRowAlreadyBelongsToDataGridView);
}
if (dataGridViewCell.OwningRow is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_CellAlreadyBelongsToDataGridViewRow);
}
Debug.Assert(!dataGridViewCell.ReadOnly);
Debug.Assert(!dataGridViewCell.Selected);
_items.Insert(index, dataGridViewCell);
dataGridViewCell.OwningRow = _owner;
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, dataGridViewCell));
}
internal void InsertInternal(int index, DataGridViewCell dataGridViewCell)
{
Debug.Assert(!dataGridViewCell.Selected);
_items.Insert(index, dataGridViewCell);
dataGridViewCell.OwningRow = _owner;
DataGridView? dataGridView = _owner.DataGridView;
if (dataGridView is not null && dataGridView.Columns.Count > index)
{
dataGridViewCell.OwningColumn = dataGridView.Columns[index];
}
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, dataGridViewCell));
}
protected void OnCollectionChanged(CollectionChangeEventArgs e)
{
_onCollectionChanged?.Invoke(this, e);
}
public virtual void Remove(DataGridViewCell cell)
{
if (_owner.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_OwningRowAlreadyBelongsToDataGridView);
}
int cellIndex = -1;
int itemsCount = _items.Count;
for (int i = 0; i < itemsCount; ++i)
{
if (_items[i] == cell)
{
cellIndex = i;
break;
}
}
if (cellIndex == -1)
{
throw new ArgumentException(SR.DataGridViewCellCollection_CellNotFound);
}
else
{
RemoveAt(cellIndex);
}
}
public virtual void RemoveAt(int index)
{
if (_owner.DataGridView is not null)
{
throw new InvalidOperationException(SR.DataGridViewCellCollection_OwningRowAlreadyBelongsToDataGridView);
}
RemoveAtInternal(index);
}
internal void RemoveAtInternal(int index)
{
DataGridViewCell dataGridViewCell = _items[index];
_items.RemoveAt(index);
dataGridViewCell.DataGridView = null;
dataGridViewCell.OwningRow = null;
if (dataGridViewCell.ReadOnly)
{
dataGridViewCell.ReadOnlyInternal = false;
}
if (dataGridViewCell.Selected)
{
dataGridViewCell.SelectedInternal = false;
}
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, dataGridViewCell));
}
}
|