在Visual Studio设计揭露枚举(标志)的集合 [英] Expose a collection of enums (flags) in Visual Studio designer

查看:142
本文介绍了在Visual Studio设计揭露枚举(标志)的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经得到的数据的类型可能会在.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的做的工作,并与物业通过<关联code> [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&LT; T&GT; 保存所选择的枚举 - 很容易重新工作名单,其中,T&GT; 如果您有.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;
    }
}

这篇关于在Visual Studio设计揭露枚举(标志)的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆