Overriding Control.Controls

If you're writing a custom control, it's nice to be able to lock off the controls collection from the outside world.

The first place one might think of going to accomplish this is the "Controls" property off of System.Windows.Forms.Control. Unfortunately, this is not a virtual property. But wait! Not all hope is lost - there is a protected method called "CreateControlsInstance" which is called when the control wants to make a child controls collection.

CreateControlsInstance can be overridden to provide a custom control collection.

protected override Control.ControlCollection CreateControlsInstance() {
return new MyReadonlyControlCollection(this);
}

Here's a really simple "read-only" control collection example:

public class MyReadonlyControlCollection : Control.ControlCollection {

public MyReadonlyControlCollection(Control owner) : base(owner) {
}

public override void Add ( System.Windows.Forms.Control value ) {
throw new NotSupportedException();
}

public override void Remove ( System.Windows.Forms.Control value ) {
throw new NotSupportedException();
}

internal void AddInternal( System.Windows.Forms.Control value ) {
base.Add(value);
}

internal void RemoveInternal( System.Windows.Forms.Control value ) {
base.Remove(value);
}

internal void RemoveAtInternal(int index) {
RemoveInternal(this[index]);
}

internal void ClearInternal() {
int count = this.Count;
for (int i = 0; i < count; i++) {
if (Count <= 0) {
break;
}
RemoveInternal(this[0]);
}
}
}

...and if you want an easy way of working with this class within your control you could add a property like so:

private MyReadonlyControlCollection PrivateControls {
get {
return this.Controls as MyReadonlyControlCollection;
}
}

So that working with your readonly collection is as easy as:

this.PrivateControls.AddInternal(b);