How to Enable Design Support in a Custom Control

How to enable design support in a custom control?

The Windows Forms designer has dedicated designer classes for most controls. The designer for a ListView is System.Windows.Forms.Design.ListViewDesigner, an internal class in the System.Design.dll assembly. This class gives you the ability to drag the column headers.

A UserControl uses the System.Windows.Forms.Design.ControlDesigner designer class. It doesn't do anything special, just puts a rectangle around the control with drag handles. You can see where this is heading: after you put your user control on a form, it is ControlDesigner that is used to design the class, ListViewDesigner is not in the picture. You thus lose the ability to drag the column headers. Also note that ControlDesigner doesn't give access to the controls inside the UC.

That's fixable however by creating your own designer. Start with Projects + Add Reference, select System.Design. You'll need to add a public property to the UC to expose the list view and apply the [DesignerSerializationVisibility] attribute to allow changed properties to be saved. And apply the [Designer] attribute to the UC class to replace the default designer. It all should resemble this (using the default names and a ListView that displays "employees"):

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design; // Note: add reference required: System.Design.dll

namespace WindowsFormsApplication1 {
[Designer(typeof(MyDesigner))] // Note: custom designer
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
}

// Note: property added
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ListView Employees { get { return listView1; } }
}

// Note: custom designer class added
class MyDesigner : ControlDesigner {
public override void Initialize(IComponent comp) {
base.Initialize(comp);
var uc = (UserControl1)comp;
EnableDesignMode(uc.Employees, "Employees");
}
}
}

The list view in the user control can now be clicked and designed as normal.

How do I add Windows Form Designer support to a custom control?

I'd recommend reading Extending Design Support on MSDN. In this case, you want a custom designer for your type, which can be specified via the DesignerAttribute decorating the type. For details, see Custom Designers.

How to add designer support for Point property on custom control?

You can add a property to a custom control of type Point that allows editing in the control's property grid using this code:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
EditorBrowsable(EditorBrowsableState.Advanced),
TypeConverter(typeof(PointConverter))]
public Point MyPointProperty { get; set; }

If you try the same sort of approach with a SizeF you'll find there's no built in .NET TypeConverter for a PointF. You can create your own though, I found one here (and copy and pasted most of the code below).

With a PointF TypeConverter you can write a property of type PointF that's editable in the property window:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
EditorBrowsable(EditorBrowsableState.Advanced),
TypeConverter(typeof(PointFConverter))]
public PointF MyPointFProperty { get; set; }

Here's the PointF type converter code found in the article linked above:

/// <summary>
/// PointFConverter
/// </summary>
public class PointFConverter : ExpandableObjectConverter
{
/// <summary>
/// Creates a new instance of PointFConverter
/// </summary>
public PointFConverter() {
}

/// <summary>
/// Boolean, true if the source type is a string
/// </summary>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
if (sourceType == typeof(string)) return true;
return base.CanConvertFrom(context, sourceType);
}

/// <summary>
/// Converts the specified string into a PointF
/// </summary>
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) {
if (value is string) {
try {
string s = (string)value;
string[] converterParts = s.Split(',');
float x = 0;
float y = 0;
if (converterParts.Length > 1) {
x = float.Parse(converterParts[0].Trim());
y = float.Parse(converterParts[1].Trim());
} else if (converterParts.Length == 1) {
x = float.Parse(converterParts[0].Trim());
y = 0;
} else {
x = 0F;
y = 0F;
}
return new PointF(x, y);
} catch {
throw new ArgumentException("Cannot convert [" + value.ToString() + "] to pointF");
}
}
return base.ConvertFrom(context, culture, value);
}

/// <summary>
/// Converts the PointF into a string
/// </summary>
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) {
if (destinationType == typeof(string)) {
if (value.GetType() == typeof(PointF)) {
PointF pt = (PointF)value;
return string.Format("{0}, {1}", pt.X, pt.Y);
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}

Is there a way to use a custom control in the designer and avoid the GAC?

Visual Studio should have no problem finding the control and loading it as long as the project that is using it has referenced the DLL. You might want to try building the project then closing and re-opening Visual Studio. There is no need for the assembly to be in the GAC.

You might also try opening the assembly in Reflector to see if it references other assemblies that you don't have. If Aero.Controls references another assembly that you haven't referenced and Visual Studio can't find it when probing for it, you will see that kind of error and GAC'ing the assemblies mentioned above would not fix that.

Custom Designer for a Control

In order to add design-time functionality like additional operations (known as Action Lists and Verbs depending on how they are provided), or dragging of visual elements like headers or split bars, you need to implement a custom designer (usually derived from ControlDesigner) that allows the Windows Forms designer to understand how to interact with your custom control at design-time.

MSDN has a lengthy section on adding design-time support for your controls. It describes everything from type converters to extender providers and designer serialization to designer customization.

Additional resources

This article on CodeProject contains information on creating designers for custom controls. There are also some useful tips here and in this other StackOverflow question.

Visual Inheritance, Design-time support for extended custom controls

As I already pointed out in the comments, the modifiers of the properties were all set to private and changing them to protected and rebuilding the solution fixed the "problem".



Related Topics



Leave a reply



Submit