如何在 .NET PropertyGrid 中显示具有重复值的枚举?

How to display an enum with duplicate values in a .NET PropertyGrid?

我有一个包含重复值的枚举。例如:

public enum DataVals : byte 
{
    C1_Route1to2 = 1,
    C4_Route3to5 = 1,
    C6_Route1to2 = 2,
    C7_Route3to5 = 2
}

C# 只是我的应用程序中的内部值。根据用户选择的路线,route 是 class 中的另一个 属性,1 可能意味着使用 C1C4 .问题是我在我的 Winform 中使用了 PropertyGrid,而这个 属性 将重复值显示为具有相同的名称。所以 C1_Route1to2 出现了两次,而不是同时出现 C1_Route1to2C4_Route3to5

如何让 PropertyGrid 显示每个唯一的名称,而不是重复值?

虽然我同意 Gabriel 的观点,但您可以使用我之前提到的 TypeConverter 实现您需要的功能。如果编辑器具有 FlagsAttribute...

,您可能需要更改编辑器以允许选择多个枚举

放置属性:

[TypeConverter(typeof(ComplexEnumConverter ))]
public enum DataVals : byte 
{
    C1_Route1to2 = 1,
    C4_Route3to5 = 1,
    C6_Route1to2 = 2,
    C7_Route3to5 = 2
}

这是转换器:

public class ComplexEnumConverter : EnumConverter
    {
        public bool IsFlagged { get; }

        public string[] EnumValues { get; }

        public ComplexEnumConverter(Type type)
            : base(type)
        {
            IsFlagged = TypeDescriptor.GetAttributes(type).OfType<FlagsAttribute>().Any();
            EnumValues = Enum.GetNames(type);
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var str = value as string;
            if (!string.IsNullOrWhiteSpace(str))
            {
                var values = str.Split(',').Select(s => s.Trim());
                var enumValue = Enum.Parse(EnumType, values.First());
                if (IsFlagged)
                {
                    var temp = (int)enumValue;
                    foreach (var item in values.Skip(1))
                    {
                        temp |= (int)Enum.Parse(EnumType, item);
                    }

                    enumValue = temp;
                }

                return enumValue;
            }

            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            var type = value?.GetType();
            if (type == EnumType)
            {
                var list = new List<string>();
                int k = (int)value;
                foreach (var item in Enum.GetNames(type))
                {
                    var current = (int)Enum.Parse(type, item);
                    if ((k & current) == current)
                    {
                        list.Add(item);
                    }
                }

                return list.Aggregate((c, n) => $"{c}, {n}");
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return context.PropertyDescriptor.PropertyType.IsEnum;
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return context.PropertyDescriptor.PropertyType.IsEnum;
        }

        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            return new StandardValuesCollection(EnumValues);
        }
    }