.net - 在 Visual Studio 设计器中公开枚举(标志)集合

标签 .net visual-studio winforms

我有一个可能显示在 .NET Forms 控件中的数据类型的枚举,我想为控件的使用者提供一个接口(interface)来过滤某些类型(设置一些标志)。位字段似乎是执行此操作的合乎逻辑的方法,不幸的是,枚举从 0 而不是 1(0、1、2、4、8、...)开始并且无法更改。

如何公开这组标志,以便可以通过编程方式或通过 Visual Studio 设计器轻松配置它?

最佳答案

你需要写一个 UITypeEditor做这项工作,并通过[EditorAttribute]将其与属性(property)相关联.

编辑 现在用示例 - 恐怕相当长 - 但幸运的是,大部分代码可以在类型之间共享。

由于零,您不能使用单个复合枚举值 - 所以在这里我使用 HashSet<T>保存选定的枚举 - 相当容易重新工作到 List<T>不过,如果您有 .NET 2.0/3.0。

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;
    }
}

关于.net - 在 Visual Studio 设计器中公开枚举(标志)集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/831612/

相关文章:

asp.net - 我的 Windows Azure 站点突然变得异常缓慢?

c# - Visual Studio 2017 中的错误 "missing assembly reference"

c# - 如何在不使最后一行空白的情况下向富文本框添加新行?

c# - Form1_Load 即使在添加处理程序后也没有触发

c# - 从窗体移植到 WPF

c# - 我应该考虑在 WCF 双工服务上使用 SignalR 吗?

c# - 在 Lucene 中搜索 TokenStream 字段

.net - 使用QueryMultiple的Dapper多重映射

c# - 如何在不显示表单的情况下打印 ReportViewer 的报告

c# - 如何在 C# 项目中使用 Scintilla .NET?