Creating controls/components from Toolbox and Initializing

I got this question today and wanted to write on it:

How does creation of controls from toolbox work? A related question is - how do we initialize the control’s properties when it gets created? A more advanced scenario is – how can we create multiple controls/components when double-clicking just a single item in the toolbox (e.g. in a Windows Forms Application double-clicking say the a DataGridView in the ‘Data Sources’ window also creates the DataSet, DataConnector and DataAdapter components along with DataGridView control on the Form. How does that work? The magic lies in interfaces IToolboxUser and ToolboxItem. IToolboxUser is an interface that is implemented by any designer that supports adding controls from the toolbox. DocumentDesigner and ComponentDocumentDesigner implement the IToolboxUser interface. When we double-click an item (control/component) in the toolbox IToolboxUser.ToolPicked() method gets called. If we drag-drop the item then the drag drop handler gets called. In either case when the control/component is about to be created, the flow of execution is as follows:

·          ToolboxItem.CreateComponents() Note: in most cases the toolbox item creates just one component. E.g. double-clicking button in the toolbox only creates a single control Button, but in the advanced scenario mentioned above we can potentially create multiple components and parent them to the DesignerHost’s RootComponent. So, if you create a custom ToolboxItem and associate it with a control (through a ToolboxItem attribute) then you could create multiple components

·          Toolbox item then gets the designer for each of the components it created and checks if they implement IComponentInitialize. If they do then IComponentInitialize.InitializeNewComponent is called. Note: This method can be overridden to initialize the properties on the component being created

As an example consider this code below that creates control on the RootComponent (in this case a Form) by using the IToolboxUser interface of the designer of the RootComponent (FormDocumentDesigner).

DesignSurface ds = new DesignSurface();

ds.BeginLoad(typeof(Form)); // loads the Form

IDesignerHost idh = ds.GetService(typeof(IDesignerHost)) as IDesignerHost;

IToolboxUser tbu = idh.GetDesigner (idh.RootComponent as IComponent) as IToolboxUser;

tbu.ToolPicked(new ToolboxItem(typeof(Button));

// Show the Form

Control view = ds.View as Control;

Form f = new Form();

f.Controls.Add(view);

view.Dock = DockStyle.Fill;

f.Show();

We could instead use a custom toolbox item that would create multiple controls. Below is a snippet of this custom toolbox item that overrides CreateComponentsCore to create 2 controls: TextBox control and MyControl.

protected override IComponent[] CreateComponentsCore(System.ComponentModel.Design.IDesignerHost host)

{

TextBox textbox = (TextBox)host.CreateComponent(typeof(TextBox));

            textbox.Parent = host.RootComponent as Control;

            MyControl myControl = (MyControl)host.CreateComponent(typeof(MyControl));

            return new IComponent[] { textbox, myControl };

}

Please let me know if you need more information of have specific comments.