Welcome to WindowsClient.net | Sign in | Join

Here are some frequently asked questions about Windows Forms and their answers.

Windows Forms FAQs

How do I persist a collection of items into code at design time?

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 
{ 
  public SomeItem() {} 
  public SomeItem( string label ) 
  { 
    this.label = label; 
  }
 
  private string label = string.Empty;
  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).

public class SomeItemCollection : IList 
{ 
  // Fields 
  private SomeItemDisplayer owner; 
  public event EventHandler Changed; 

  public SomeItemCollection( SomeItemDisplayer owner ) 
  { this.owner = owner; }
 
  internal ArrayList InnerArray { get { return owner.someItems; } } 
                
  public void OnChanged() 
  { 
    if ( Changed != null ) 
       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 ] 
  { 
    get 
    { 
      ValidateIndex( index );
      return (SomeItem) InnerArray[ index ]; 
    } 
    set 
    { 
      ValidateNotNull( value, "value" );
      ValidateIndex( index );
      InnerArray[ index ] = value; 
      OnChanged(); 
    } 
  }
  
  public void AddRange( object[] items ) 
  { 
    InnerArray.AddRange( items ); 
    OnChanged(); 
  }
 
  /// <summary>
  /// This implementation for the Item property for the IList interface. Its 
  /// property type is object. 
  /// </summary>
  object IList.this[ int index ] 
  { 
    set { this[ index ] = (SomeItem) value; } // forward call to public indexer 
    get { return this[ index ]; } // forward call to public indexer 
  } 

  public IEnumerator GetEnumerator() // IEnumerable
  { return InnerArray.GetEnumerator(); }

  public int Count // ICollection
  { get { return InnerArray.Count; } }
 
  public void RemoveAt( int index ) // IList
  { 
    ValidateIndex( index );
    InnerArray.RemoveAt( index ); 
    OnChanged(); 
  }
 
  public void Remove( object value ) // IList
  { 
    int n = InnerArray.IndexOf( value, 0 ); 
    if ( n != -1 ) RemoveAt( n ); 
  }

  public void Insert( int index, object item ) // IList
  {
    ValidateNotNull( item, "item" );
    ValidateIndex( index );
    InnerArray.Insert( index, item ); 
    OnChanged(); 
  }
 
  public int IndexOf( object value ) // IList
  {
    ValidateNotNull( value, "value" );
    return InnerArray.IndexOf( value, 0 ); 
  } 

  public bool IsReadOnly // IList
  { get { return false; } }
 
  public void Clear() // IList
  { 
    InnerArray.Clear(); 
    owner.Invalidate(); 
  }
 
  public bool Contains( object value ) // IList
  { 
    return IndexOf( value ) != -1; 
  }
 
  void System.Collections.ICollection.CopyTo( Array dest, int index ) 
  { 
    for ( int n = 0; n < InnerArray.Count; ++n ) 
      dest.SetValue( InnerArray[ n ], n + index ); 
  }

  int System.Collections.IList.Add( object item ) 
  { 
    int n = 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; } }
 
  private void ValidateIndex( int index )
  {
    if ( index < 0 || index >= InnerArray.Count ) 
      throw new ArgumentOutOfRangeException( 
        String.Format( "Invalid Argument {0}: {1}", "index", index.ToString() ) ); 
  }

  private void ValidateNotNull( object o, string name )
  {
    if ( o == null ) throw new ArgumentNullException( name ); 
  }
}

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 ); } 

Contributed from George Shepherd's Windows Forms FAQ



Page view counter