如何在 .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
可能意味着使用 C1
或 C4
.问题是我在我的 Winform
中使用了 PropertyGrid
,而这个 属性 将重复值显示为具有相同的名称。所以 C1_Route1to2
出现了两次,而不是同时出现 C1_Route1to2
和 C4_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);
}
}
我有一个包含重复值的枚举。例如:
public enum DataVals : byte
{
C1_Route1to2 = 1,
C4_Route3to5 = 1,
C6_Route1to2 = 2,
C7_Route3to5 = 2
}
值 C#
只是我的应用程序中的内部值。根据用户选择的路线,route
是 class 中的另一个 属性,1
可能意味着使用 C1
或 C4
.问题是我在我的 Winform
中使用了 PropertyGrid
,而这个 属性 将重复值显示为具有相同的名称。所以 C1_Route1to2
出现了两次,而不是同时出现 C1_Route1to2
和 C4_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);
}
}