Is there a way for hiding some enum values for specific property of class?
Asked Answered
T

1

9

I have enum lets say for example:

public enum Color
{
  red,
  green,
  blue
}

And have two classes. which have property of enum.

public class ClassA
{
    public Color Color{get;set;}
}

public class ClassB
{
    [InvisibleFlag(Color.red)]  // I want something like that
    public Color Color{get;set;}
}

Now in Windows Forms Designer, I want to hide the red flag only from the Color enumeration for ClassB only.

I know that I can create a separated enum. but why duplicate values? I gave a simple example only.

Something I guess might help for superior who can help me at it.

Descriptor API. which I hate. ;(

Maybe something like TypeDescriptor.AddAttributes(object, new BrowsableAttribute(false));

This answer will not work in this case. I don't want to apply Browsable attribute to the enum flags because it hides that flag in property grid for all classes. I want to be able to hide specific enum values for specific classes only, not for all classes.

Tippler answered 25/11, 2019 at 1:10 Comment(2)
You can use a TypeConverter, where, in the GetStandardValues() method override, you can filter the Enum values to return a new collection that excludes the Value specified by the InvisibleFlag attribute. You also have to override CanConvertFrom and ConvertFrom, to convert the string representation of the Enum to an Enum value. You also need to create the InvisibleFlag custom attribute, with two constructors: one that accepts the enum type and one that accepts a string. A [DefaultValue(...)] attribute should be used, to avoid a default assignment to an excluded enum value.Phillips
@Ňɏssa: "This has nothing at all to do with Windows forms designer" -- doesn't it? it seems like they are asking specifically to adjust the behavior in the Designer. I.e. to prevent the red value from being an option in the property grid for the class when shown in the Designer.Barthold
B
13

The class which helps you to show the enum values in PropertyGrid is EnumConverter and the method which is responsible to list enum values in GetStandardValues.

So as an option, you can can create a custom enum converter class by deriving from EnumConverter and the override its GetStandardValues to return standard values based on a specific attribute which you have for the property.

How to get context information like attributes of property in TypeConverter methods?

An instance of ITypeDescriptorContext class is passed to context parameter of the TypeConverter method. Using that class, you have access to the object which is being edited and the property descriptor of the property which is being edited has some useful properties. Here you can rely on
PropertyDescriptor property of the context and get the Attributes and check if the specific attribute in which we are interested, has been set for the property.

Example

[TypeConverter(typeof(ExcludeColorTypeConverter))]
public enum Color
{
    Red,
    Green,
    Blue,
    White,
    Black,
}
public class ExcludeColorAttribute : Attribute
{
    public Color[] Exclude { get; private set; }
    public ExcludeColorAttribute(params Color[] exclude)
    {
        Exclude = exclude;
    }
}
public class ExcludeColorTypeConverter : EnumConverter
{
    public ExcludeColorTypeConverter() : base(typeof(Color))
    {
    }
    public override StandardValuesCollection GetStandardValues(
        ITypeDescriptorContext context)
    {
        var original = base.GetStandardValues(context);
        var exclude = context.PropertyDescriptor.Attributes
            .OfType<ExcludeColorAttribute>().FirstOrDefault()?.Exclude
            ?? new Color[0];
        var excluded = new StandardValuesCollection(
            original.Cast<Color>().Except(exclude).ToList());
        Values = excluded;
        return excluded;
    }
}

As an example of the usage:

public class ClassA
{
    public Color Color { get; set; }
}

public class ClassB
{
    [ExcludeColor(Color.White, Color.Black)]
    public Color Color { get; set; }
}

enter image description here

Bona answered 25/11, 2019 at 7:23 Comment(3)
Reza i really want to say that a real man is real man, you do harder things for us easy for you. Thanks you a real man.Tippler
Reza, sorry but I omit the Values = excluded, and code still works ? is this property important?Tippler
Color property of ClassA is an example of a property which doesn't have ExcludeColor and it still works. In fact by decorating the enum using [TypeConverter(typeof(ExcludeColorTypeConverter))] we are telling all properties of this enum type should use this type converter. Then in GetStandardValues method of ExcludeColorTypeConverter we check if the property has any ExcludeColor attribute, then we exclude those values from list, otherwise we show original list values (all enums).Bona

© 2022 - 2024 — McMap. All rights reserved.