我已经得到的数据的类型可能会在.NET窗体控件显示一个枚举,我想为消费者提供控制的接口过滤掉一些类型的(设置一些标志)。位字段似乎做这个逻辑方式,不幸的是,该枚举从0开始,而不是1(0,1,2,4,8,...),并且不能被改变。
I've got an enum of types of data that might be shown in a .NET Forms control and I want to provide an interface for consumers of the control to filter some of the types (set some of the flags). A bit field seems the logical way to do this, unfortunately, the enum starts at 0 rather than 1 (0, 1, 2, 4, 8, ...) and can't be changed.
我怎样才能让本组标志,以便它可以很容易地编程方式或通过Visual Studio设计配置?
How can I expose this set of flags so that it can be easily configured programmatically or through the Visual Studio designer?
推荐答案
您需要编写一个 UITypeEditor的
做的工作,并与物业通过 [EditorAttribute] 。
You would need to write a UITypeEditor
to do the work, and associate it with the property via .
修改现在的例子 - 一个相当漫长的,我害怕 - 但是大部分的code能类型之间进行共享,幸运的是
edit now with example - a fairly long one, I'm afraid - but most of the code can be shared between types, fortunately.
您无法使用,因为零一个单一的复合枚举值 - 所以在这里我使用了一个的HashSet< T>
保存所选择的枚举 - 很容易重新工作名单,其中,T>
如果您有.NET 2.0 / 3.0,但
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;
}
}
相关推荐
最新文章