This is a migrated thread and some comments may be shown as answers.

Cannot add a new item with a grid datasource implementing IList<T>

5 Answers 172 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Francois
Top achievements
Rank 1
Francois asked on 05 May 2011, 05:04 PM
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):
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

5 Answers, 1 is accepted

Sort by
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 06 May 2011, 08:23 AM
Hello Francois,

Why don't you just implement BindingList<T>, it provides more functionality and it is better for overall binding (from my experience and other resources)

Something like this:
public class TestCollection : BindingList<SomeClass>
{
    protected override void InsertItem(int index, Test item)
    {
        base.InsertItem(index, item);
 
        MessageBox.Show("insert item called");
    }
 
    protected override void RemoveItem(int index)
    {
        base.RemoveItem(index);
 
        MessageBox.Show("delete item called");
    }
}

Hope this helps, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga

Telerik WinForms MVP
0
Julian Benkov
Telerik team
answered on 10 May 2011, 11:54 AM
Hello Francois,

Francois, please check the solution suggested by Emanuel. It describes how to create a BindingList<T> list collection that supports all CRUD operations.

Please do not hesitate to contact us if you have further questions.

Greetings,
Julian Benkov
the Telerik team
Q1’11 SP1 of RadControls for WinForms is available for download; also available is the Q2'11 Roadmap for Telerik Windows Forms controls.
0
Francois
Top achievements
Rank 1
answered on 16 Jun 2011, 07:12 PM
Finally, I implemented IBindingList and it working like properly.

Thanks!
0
Robert
Top achievements
Rank 1
answered on 16 Nov 2011, 02:29 PM
Hi Francois,

Im using this for the items of my list.

 

EmployeeContext context = new EmployeeContext();
EntityQuery<EmployeeMaster> qry = context.GetEmployeeMastersQuery();

 

LoadOperation<EmployeeMaster> operation = context.Load(qry);

EmployeeManpowerList.ItemsSource = operation.Entities;


im using RadDragAndDropManager.

IList items = wishlist.ItemsSource as IList;

foreach (object draggedItem in draggedItems)

{

items.Add(draggedItem); ***** This gives me an error (says collection is read only....)

}

Can you help me ?
Thanks.


0
Julian Benkov
Telerik team
answered on 21 Nov 2011, 12:58 PM
Hello Robert,

Please check what the ItemSource property of the wishlist object contains. You must bind to an IList object to support insert operation in the list. If you are using LINQ query, you can convert the result using the ToList() extension.

I hope this helps.

Best wishes,
Julian Benkov
the Telerik team

Q2’11 SP1 of RadControls for WinForms is available for download (see what's new); also available is the Q3'11 Roadmap for Telerik Windows Forms controls.

Tags
GridView
Asked by
Francois
Top achievements
Rank 1
Answers by
Emanuel Varga
Top achievements
Rank 1
Julian Benkov
Telerik team
Francois
Top achievements
Rank 1
Robert
Top achievements
Rank 1
Share this question
or