我在PropertyGrid中显示对象的属性。其中一个属性是枚举。因此,它使用组合框编辑器显示,该编辑器列出了枚举的所有值。这一切都很棒,但我需要在运行时过滤枚举值列表。我不能用Browsable属性装饰一些枚举值,因为我想隐藏哪些值会有所不同。目前我倾向于使用自定义UITypeEditor,但我认为我应该首先与智能人员核实。
答案 0 :(得分:5)
TypeConverter
可能就是您所需要的,特别是如果合法子集“时刻变化”。鉴于枚举:
public enum AnimalSpecies
{
Canine, Feline, Rodent, Dragon, Unicorn, Robot
}
...用于财产:
public class Animal
{
...
[TypeConverter(typeof(AnimalSpeciesConverter))]
public AnimalSpecies Species { get; set; }
如果你装饰枚举,转换器将适用于使用它的任何/所有东西;在财产上,它只影响那个。对于转换器,您需要覆盖GetStandardValues()
:
class AnimalSpeciesConverter : TypeConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
Animal test = context.Instance as Animal;
if (test != null)
return true;
else
return base.GetStandardValuesSupported();
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
string[] names = Enum.GetNames(typeof(AnimalSpecies))
.Where(x => !x.StartsWith("Rob")).ToArray();
return new StandardValuesCollection(names);
}
}
GetStandardValuesSupported()
返回true表示TypeConverter
可以并且将提供值。 GetStandardValuesExclusive()
表示,用户无法选择输入自己的值。 GetStandardValues()
过滤列表并返回新子集。 结果:
如果过滤逻辑更复杂,您可能希望让类实例确定内容。或者你可能只是喜欢这种逻辑留在课堂上。为此,我喜欢使用界面:
public interface IValuesProvider
{
string[] GetValues();
}
public class Animal : IValuesProvider
{
public string Name { get; set; }
[TypeConverter(typeof(AnimalSpeciesConverter))]
public AnimalSpecies Species { get; set; }
public int Value { get; set; }
...
public string[] GetValues()
{
List<string> names = Enum.GetNames(typeof(AnimalSpecies)).ToList();
// your logic here
if (Value < 10)
names.Remove(AnimalSpecies.Feline.ToString());
else if (Value < 50)
names.Remove(AnimalSpecies.Robot.ToString());
return names.ToArray();
}
现在,当PropertyGrid请求值时,我们可以从实例中获取它们:
class AnimalSpeciesConverter : TypeConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
IValuesProvider test = context.Instance as IValuesProvider;
if (test != null)
return true;
else
return base.GetStandardValuesSupported();
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
IValuesProvider item = context.Instance as IValuesProvider;
return new StandardValuesCollection(item.GetValues());
}
}
作为替代方法,如果您不喜欢以这种方式公开它并通过Reflection获取值,则可以跳过界面并将GetValues
方法设为私有。在这种情况下,仅当方法存在时,我才可以为GetStandardValuesSupported()
返回true。这样你就不会遇到Get...Supported()
返回true然后无法提供它们的情况。
这是动态的:每次下拉打开时都会刷新/重新填充值列表。每次更改Value
时,下拉列表每次打开时都会更新。