Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

UserControl Prompts for ControlName after Drop in the Designer

0.00/5 (No votes)
2 Jul 2010 1  
UserControl with a custom ControlDesigner that prompts for the ControlName after drop in the Designer
2.png

Introduction

In this article, I will show you how to change the control name of your own user control by prompting for it during/after dropping onto the Form in the Designer. So the user must enter a ControlName before he has the ability to change other things. This article could also be useful for people who want, i.e., to show a licensing dialog or something else directly after the drop onto the form.

The code I deliver shows a user control using the ControlDesigner for DesignTime support. The ControlDesigner implements the logic to prompt for the ControlName during DesignTime. Additional, I wrote a class called NameCreationService that implements the "default" logic of creating names and the logic for showing a Modal Dialog where you can enter a control name.

Background

Somebody had the question at the C# forum about how to prompt for the control name if the user drops his user control onto the form using the Designer in VS or #Develop. I've found that question interesting but not very useful for that case because it would annoy me if I always have to specify the name directly after the drop.

Using the Code

First, we need to create a new class MyControlDesigner, be sure it is derived from System.Windows.Forms.Design.ControlDesigner. As you can see at the sample code of ControlDesigner, we need to override the Initialize(IComponent) to hold our user control and InitializeNewComponent(IDictionary) that functionality will prompt for the control name.

Second we need a class NameCreationService that implements the logic for creating names during the design time. I used the code I wrote for a project a long time ago... and extended the functionality of CreateName(IContainer, Type) with a check against our user control. In that case, I want to show a modal dialog where the user can insert a string instead of generating the name using the information the container brings.

public string CreateName(IContainer container, Type dataType)
{
	if(container==null)
	{
		throw new ArgumentException("container");
	}
	if(dataType==null)
	{
		throw new ArgumentException("dataType");
	}
	
	string name = string.Empty;
	
        if(dataType == typeof(MyControl))
	{
		// Prompt for the name using a Dialog
		name = PromptName(container, dataType);
	}
	else
	{
		// use the normal way to generate the name
		name = GenerateDefaultName(container, dataType);
	}
	
	return name;
}

public string GenerateDefaultName(IContainer container, Type dataType)
{
	// look to see if the container already has this type
	// of component, if it does, then iterate until you
	// find a unique name
	int count = 1;
	string name = dataType.Name + count.ToString();
	if(container.Components[name]!=null)
	{
		for(int i=1; i<container.Components.Count; i++)
		{
			name = dataType.Name + (i+1).ToString();
			if(container.Components[name]==null)
			{
				break;
			}
		}
	}
	
	return name;
}

public string PromptName(IContainer container, Type dataType)
{
	string name = dataType.Name;
	do
	{
		using (EnterControlNameDialog dlg = new EnterControlNameDialog())
		{
			dlg.ControlName = name;
			
			DialogResult dlgRes = 
				dlg.ShowDialog(container as IWin32Window);
			if(dlgRes == DialogResult.OK)
			{
				name = dlg.ControlName;
			}
			else
			{
				name = GenerateDefaultName(container, dataType);
			}
		}
	}while(!IsValidName(name));
	
	return name;
}

In the InitializeNewComponent(IDictionary), we first let the base class do its stuff and after that we will get the IDesignerHost of the current IDE Designer using the GetService(typeof(IDesignerHost)). The IDesignerHost is used to get the access to the current components the designer holds. The next step would be to create an instance of the class NameCreationService we wrote before calling the function CreateName using the IDesignerHost.Container and Component.GetType() as parameter. The returned value will be set to the component property name using the PropertyDescriptor. You see the whole steps below are shown as images.

ControlDesigner Code

/// <summary>
/// Description of Designer.
/// </summary>
[System.Security.Permissions.PermissionSet
(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyControlDesigner : System.Windows.Forms.Design.ControlDesigner
{
	private MyControl control ;
	public override void Initialize(IComponent component)
	{
		base.Initialize(component);
		
		control = component as MyControl;
	}

	public override void InitializeNewComponent
		(System.Collections.IDictionary defaultValues)
	{
		base.InitializeNewComponent(defaultValues);

		PropertyDescriptor namePropDesc =
   		     TypeDescriptor.GetProperties(Component)["Name"];

    		IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
    		Design.NameCreationService naming = new NameCreationService(host);
    		string name = naming.CreateName(host.Container, Component.GetType());

    		if (namePropDesc != null &&
    		    namePropDesc .PropertyType == typeof(string) &&
    		    !namePropDesc .IsReadOnly &&
    		    namePropDesc .IsBrowsable)
    		{
    		    namePropDesc .SetValue(Component, name);
   		}
	}
}

Step-by-Step

  1. The Empty form is shown in the designer (right) and the user control MyControl (left).

    0.png

  2. Drag MyControl and drop it over the empty form.

    1.png

  3. Directly after the drop action a dialog is modal shown where the user can enter the name of the control.

    2.png

  4. Change the current name to MyControl1234 and press button Set Name.

    3.png

  5. The PropertyGrid shows the selected control MyControl including the entered name "MyControl1234" at the property name.

    4.png

  6. Drag & Drop a second MyControl on the form and press the button Default to let the NameCreationService generate the name using the information coming from the Designer.

    5.png

  7. The "use-case" result shows how the designer would work. The name of the control is now MyControl2. (See property name in propertygrid.)

    6.png

And that's it. I hope I could help somebody with this article about interacting with the designer and a self-written user control during design time.

Points of Interest

Yeah, now I know how I would start licensing my controls during DesignTime :).

History

  • 2010/07/01
    • First version released

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here