You would need to write a UITypeEditor
to do the work, and associate it with the property via [EditorAttribute]
.
edit now with example - a fairly long one, I'm afraid - but most of the code can be shared between types, fortunately.
You can't use a single composite enum value because of the zero - so here I'm using a HashSet<T>
to hold the selected enums - fairly easy to re-work to List<T>
if you have .NET 2.0/3.0, though.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
public class MyControl : UserControl
{
public MyControl()
{
Values = new HashSet<MyEnum>();
}
[Editor(typeof(MyEnumSetEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(MyEnumSetConverter))]
public HashSet<MyEnum> Values { get; set; }
}
public enum MyEnum
{ // numbers as per the question...
A = 0, B = 1, C = 2, D = 4, E = 8
}
class MyEnumSetEditor : EnumSetEditor<MyEnum> { }
class MyEnumSetConverter : EnumSetConverter<MyEnum> { }
// from here down is shared between types
abstract class EnumSetConverter<T> : TypeConverter where T : struct
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if(destinationType == typeof(string))
{
HashSet<T> set = (HashSet<T>)value;
if (set == null) return "(null)";
StringBuilder sb = new StringBuilder();
foreach (T item in Enum.GetValues(typeof(T)))
{
if (set.Contains(item))
{
if (sb.Length > 0) sb.Append(", ");
sb.Append(item);
}
}
return sb.ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
public abstract class EnumSetEditor<T> : UITypeEditor where T : struct
{
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override bool IsDropDownResizable
{
get { return true; }
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService svc = (IWindowsFormsEditorService)
provider.GetService(typeof(IWindowsFormsEditorService));
HashSet<T> set = value as HashSet<T>;
if (svc != null && set != null)
{
UserControl ctrl = new UserControl();
CheckedListBox clb = new CheckedListBox();
clb.Dock = DockStyle.Fill;
Button btn = new Button();
btn.Dock = DockStyle.Bottom;
foreach (T item in Enum.GetValues(typeof(T)))
{
clb.Items.Add(item, set.Contains(item));
}
ctrl.Controls.Add(clb);
ctrl.Controls.Add(btn);
btn.Text = "OK";
btn.Click += delegate
{
set.Clear();
foreach (T item in clb.CheckedItems)
{
set.Add(item);
}
svc.CloseDropDown();
};
svc.DropDownControl(ctrl);
}
return value;
}
}