How can I persist a collection of items into code

Platform: WinForms| Category: Tips

The CollectionEditor allows adding and removing items from a collection at design time. If the items in this collection implement IComponent or if they are derived from Component, the items in your collection can be persisted in code.

Download collectioneditorsample.zip for a complete sample project.

Here are some steps you should follow:

1) Make sure your item is derived from Component or implements Icomponent.
For example:


  public class SomeItem : Component
  {
    private string label = '''';

    public SomeItem()
    {
    }

    public SomeItem(string label)
    {
      this.label = label;
    }

    public string Label 
    {
      get 
      { 
        return label; 
      }
      set 
      { 
        label = value; 
      }
    }

    public override string ToString()
    {
      return String.Format(''SomeItem: ( Label = ’{0}’ )'', label);
    }
  }

2) Next implement your Collection. You have to implement the Ilist interface. The CollectionEditor will determine the type of instances to be added to your collection using reflection inspecting the return type of the Item property (Indexer).


    [
    Description(''The set of properties to be edited with CollectionEditor.''), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
    Editor(typeof(System.ComponentModel.Design.CollectionEditor), 
      typeof(System.Drawing.Design.UITypeEditor))
    ]
    public SomeItemCollection SomeItems 
    {
      get 
      {
        if (someItemCollection == null) 
        {
          someItemCollection = CreateItemCollection();
        }
        return someItemCollection;
      }
    }

    protected SomeItemCollection CreateItemCollection()
    {
      return new SomeItemCollection(this);
    }

    public class SomeItemCollection : IList
    {
      // Fields
      private SomeItemDisplayer owner;
      public event EventHandler Changed;
            
      // Constructors
      public SomeItemCollection(SomeItemDisplayer owner)
      {
        this.owner = owner;
      } 

      internal ArrayList InnerArray 
      { 
        get
        {
          return owner.someItems;
        } 
      }
      
      public void OnChanged()
      {
        if (this.Changed != null)
          this.Changed(this, EventArgs.Empty);
      }
            
      /// 
      /// The CollectionEditor will determine the type of objects to be created by
      /// looking at the property type of the following method. CollectionEditor
      /// internally uses reflection to get the PropertyInfo for the ''Item'' property. 
      /// This method must be public.
      /// 
      public SomeItem this[int index] 
      { 
        set
        {
          if (value == null) 
            throw new ArgumentNullException(''value'');

          if (index < 0 || index >= this.InnerArray.Count) 
            throw new ArgumentOutOfRangeException(String.Format(''Invalid Argument {0}: {1}'', ''index'', index.ToString()));

          this.InnerArray[index] = value;
          OnChanged();
        } 
        get
        {
          if (index < 0 || index >= this.InnerArray.Count)
            throw new ArgumentOutOfRangeException(''Invalid Argument {0}: {1}'', ''index'', index.ToString());
          return (SomeItem) this.InnerArray[index];
        } 
      }

      public void AddRange(object[] items)
      {
        InnerArray.AddRange(items);
        OnChanged();
      }
            
      /// 
      /// This implementation for the Item property for the IList interface. It’s
      /// property type is object.
      /// 
      object IList.this[int index] 
      { 
        set
        {
          // forward call to public indexer 
          this[index] = (SomeItem) value;
        } 
        get
        {
          // forward call to public indexer
          return this[index];
        } 
      }

      public /*IEnumerable*/ IEnumerator GetEnumerator()
      {
        return InnerArray.GetEnumerator();
      } 
            
            
      public /*ICollection*/ int Count 
      { 
        get
        {
          return InnerArray.Count;
        } 
      }
            
      public /*IList*/ void RemoveAt(int index)
      {
        if (index < 0 || index >= this.InnerArray.Count) 
          throw new ArgumentOutOfRangeException(String.Format(''Invalid Argument {0}: {1}'', ''index'', index.ToString()));

        this.InnerArray.RemoveAt(index);
        OnChanged();
      } 
            
            
      public /*IList*/ void Remove(object value)
      {
        int n = this.InnerArray.IndexOf(value,0);
        if (n != -1) 
          this.RemoveAt(n);
      } 
            
            
      public /*IList*/ void Insert(int index, object item)
      {
        if (item == null) 
          throw new ArgumentNullException(''item'');
        if (index < 0 || index > this.InnerArray.Count)
          throw new ArgumentOutOfRangeException(String.Format(''Invalid Argument {0}: {1}'',''index'', index.ToString()));

        this.InnerArray.Insert(index,item);
        OnChanged();
      } 
            
            
      public /*IList*/ int IndexOf(object value)
      {
        if (value == null)
          throw new ArgumentNullException(String.Format(''Invalid Argument {0}: {1}'',''value'', ''null''));
        return this.InnerArray.IndexOf(value,0);
      } 
            
            
      public /*IList*/ bool IsReadOnly 
      { 
        get
        {
          return false;
        } 
      }
            
      public /*IList*/ void Clear()
      {
        InnerArray.Clear();
        this.owner.Invalidate();
      } 
            
            
      public /*IList*/ bool Contains(object value)
      {
        return this.IndexOf(value) != -1;
      } 
            
      void System.Collections.ICollection.CopyTo(Array dest, int index)
      {
        int count = this.InnerArray.Count;
        for (int n1 = 0; n1 < count; n1++)
          dest.SetValue(this.InnerArray[n1], (n1 + index));
      } 
            
            
      int System.Collections.IList.Add(object item)
      {
        int n = this.InnerArray.Add(item);
        OnChanged();
        return n;
      } 
            
            
      bool System.Collections.IList.IsFixedSize
      {
        get 
        {
          return false;
        } 
      } 
            
            
      bool System.Collections.ICollection.IsSynchronized
      {
        get 
        { 
          return false;
        } 
      } 
            
            
      object System.Collections.ICollection.SyncRoot
      {
        get
        {
          return this;
        } 
      } 
            
    }

3) Reference this collection in your control or component that should be designable. You need to supply a DesignerSerializationVisibility and an Editor attribute:


    private SomeItemCollection someItemCollection = null;
    ArrayList someItems = new ArrayList();
    
    [
    Description(''The set of properties to be edited with CollectionEditor.''), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content), 
    Editor(typeof(System.ComponentModel.Design.CollectionEditor), 
      typeof(System.Drawing.Design.UITypeEditor))
    ]
    public SomeItemCollection SomeItems 
    {
      get 
      {
        if (someItemCollection == null) 
        {
          someItemCollection = CreateItemCollection();
        }
        return someItemCollection;
      }
    }

    protected SomeItemCollection CreateItemCollection()
    {
      return new SomeItemCollection(this);
    }

Share with

Related FAQs

Couldn't find the FAQs you're looking for?

Please submit your question and answer.