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))
{
name = PromptName(container, dataType);
}
else
{
name = GenerateDefaultName(container, dataType);
}
return name;
}
public string GenerateDefaultName(IContainer container, Type dataType)
{
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
[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
- The Empty form is shown in the designer (right) and the user control
MyControl
(left).
- Drag
MyControl
and drop it over the empty form.
- Directly after the drop action a dialog is modal shown where the user can enter the name of the control.
- Change the current name to
MyControl1234
and press button Set Name.
- The
PropertyGrid
shows the selected control MyControl
including the entered name "MyControl1234
" at the property name.
- 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.
- The "use-case" result shows how the designer would work. The name of the control is now
MyControl2
. (See property name in propertygrid
.)
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