在PropertyGrid中

时间:2016-03-24 00:19:00

标签: c# .net enums propertygrid

我在PropertyGrid中显示对象的属性。其中一个属性是枚举。因此,它使用组合框编辑器显示,该编辑器列出了枚举的所有值。这一切都很棒,但我需要在运行时过滤枚举值列表。我不能用Browsable属性装饰一些枚举值,因为我想隐藏哪些值会有所不同。目前我倾向于使用自定义UITypeEditor,但我认为我应该首先与智能人员核实。

1 个答案:

答案 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()过滤列表并返回新子集。

结果:

enter image description here 没有机器人!

如果过滤逻辑更复杂,您可能希望让类实例确定内容。或者你可能只是喜欢这种逻辑留在课堂上。为此,我喜欢使用界面:

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时,下拉列表每次打开时都会更新。