We're using a custom collection to handle the modifications to the items bound to the RadGridView. Everything's working as expected for all but adding items. We've found out that the Telerik grid is using IList<T> data sources as IList, which means that our custom collection have to implement it as well, in order to respect our logic.
When the grid is trying to add a new item to the collection, the grid calls the IList.Add(object item) instead of IList<T>.Add(T item).
The error message displayed by the grid is "The collection is read-only."
We would expect the grid to determine the proper type of the collection in the data source.
Current version (without IList implementation):
When the grid is trying to add a new item to the collection, the grid calls the IList.Add(object item) instead of IList<T>.Add(T item).
The error message displayed by the grid is "The collection is read-only."
We would expect the grid to determine the proper type of the collection in the data source.
Current version (without IList implementation):
public class EntityStateCollection<T> : IList<T> where T : new(){ #region Membres private List<EntityState<T>> _entityStates; private Enumerator<T> _innerEnumerator; public event EventHandler ItemAdded; public event EventHandler ItemDeleted; public event EventHandler ItemModified; #endregion #region Enumerator [Serializable, StructLayout(LayoutKind.Sequential)] public struct Enumerator<T> : IEnumerator<T>, IDisposable, IEnumerator where T : new() { private List<EntityState<T>> list; private int index; private T current; internal Enumerator(List<EntityState<T>> list) { this.list = list; this.index = 0; this.current = default(T); } public void Dispose() { } public bool MoveNext() { List<EntityState<T>> list = this.list; if (this.index < list.Count) { this.current = list[this.index].InnerObject; this.index++; return true; } else { this.current = default(T); return false; } } public T Current { get { return this.current; } } object IEnumerator.Current { get { return this.Current; } } void IEnumerator.Reset() { this.index = 0; this.current = default(T); } } #endregion Enumerator public EntityStateCollection() { _entityStates = new List<EntityState<T>>(); _innerEnumerator = new Enumerator<T>(_entityStates); } public void SetModified(T item) { EntityState<T> entity = _entityStates[this.IndexOf(item)]; if (entity.ObjectState != State.Added) { entity.ObjectState = State.Modified; this.ItemModified(entity, null); } } /// <summary> /// Returns true if all T entities are at Current state. /// </summary> /// <returns></returns> public bool IsInCurrentState() { for (int i = 0; i < _entityStates.Count; i++) { if (_entityStates[i].ObjectState != State.Current) { return false; } } return true; } public EntityState<T> GetEntityState(int i) { return _entityStates[i]; } /// <summary> /// Add a list of T objects to the collection with the Current state /// </summary> /// <param name="lst"></param> public void AddRange(List<T> lst) { foreach (T item in lst) { _entityStates.Add(new EntityState<T>(State.Current, item)); //this.ItemAdded(_entityStates[this.IndexOf(item)], null); } } #region IList<T> Membres public int IndexOf(T item) { int itemIndex = -1; for (int i = 0; i < _entityStates.Count; i++) { if (_entityStates[i].InnerObject.Equals(item)) { itemIndex = i; break; } } return itemIndex; } public void Insert(int index, T item) { _entityStates.Insert(index, new EntityState<T>(State.Added, item)); this.ItemAdded(_entityStates[index], null); } public void RemoveAt(int index) { _entityStates[index].ObjectState = State.Deleted; this.ItemDeleted(_entityStates[index], null); } public T this[int index] { get { return _entityStates[index].InnerObject; } set { _entityStates[index].InnerObject = value; } } #endregion #region ICollection<T> Membres public void Add(T item) { _entityStates.Add(new EntityState<T>(State.Added, item)); this.ItemAdded(_entityStates[this.IndexOf(item)], null); } public void Clear() { _entityStates.Clear(); } public bool Contains(T item) { for (int i = 0; i < _entityStates.Count; i++) { if (_entityStates[i].InnerObject.Equals(item)) { return true; } } return false; } public void CopyTo(T[] array, int arrayIndex) { throw new NotImplementedException(); } public int Count { get { return _entityStates.Count; } } public bool IsReadOnly { get { return false; } } public bool Remove(T item) { for (int i = 0; i < _entityStates.Count; i++) { if (_entityStates[i].InnerObject.Equals(item)) { _entityStates[i].ObjectState = State.Deleted; this.ItemDeleted(_entityStates[i], null); return true; } } return false; } #endregion #region IEnumerable et IEnumerable<T> Membres public IEnumerator<T> GetEnumerator() { return this._innerEnumerator; } IEnumerator IEnumerable.GetEnumerator() { return this._innerEnumerator; } #endregion