Question


Est-il possible de faire une condition d'attribut « Browsable », de sorte que la propriété qui l'applique sera parfois apparaître dans la page de propriétés et parfois pas?
merci:)

Était-ce utile?

La solution

Il n'y a pas moyen facile.

Vous pouvez éventuellement travailler ceci en mettant en œuvre ICustomTypeDescriptor. Voici un bon article sur mise en œuvre ICustomTypeDescriptor.

Vous pouvez associer votre ControlDesigner avec votre classe et passer outre le Suppression certaines propriétés de la grille des propriétés.

Autres conseils

Je ne suis pas sûr que cela correspond à votre situation, mais vous pouvez ajuster la décoration « Browsable » lors de l'exécution en appelant la fonction ci-dessous.

/// <summary>
/// Set the Browsable property.
/// NOTE: Be sure to decorate the property with [Browsable(true)]
/// </summary>
/// <param name="PropertyName">Name of the variable</param>
/// <param name="bIsBrowsable">Browsable Value</param>
private void setBrowsableProperty(string strPropertyName, bool bIsBrowsable)
{
    // Get the Descriptor's Properties
    PropertyDescriptor theDescriptor = TypeDescriptor.GetProperties(this.GetType())[strPropertyName];

    // Get the Descriptor's "Browsable" Attribute
    BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
    FieldInfo isBrowsable = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

    // Set the Descriptor's "Browsable" Attribute
    isBrowsable.SetValue(theDescriptorBrowsableAttribute, bIsBrowsable);
}

Vous pouvez le faire en fournissant un modèle de type personnalisé; au simple niveau, vous pouvez fournir un TypeDescriptor personnalisé pour votre type dérivé de ExpandableObjectConverter et simplement inclure / exclure la propriété donnée au gré - mais cela ne fonctionne qu'avec PropertyGrid - utilisé par la page de propriétés. Une approche plus complexe consiste à utiliser ICustomTypeDescriptor / TypeDescriptionProvider - cela peut alors travailler à l'intérieur des choses comme DataGridView

une amélioration @ réponse de neoikon ci-dessus et pour éviter l'exception Ganesh mentionné dans les commentaires, voici une version qui utilise des médicaments génériques pour obtenir le type:

    /// <summary>
    /// Set the Browsable property.
    /// NOTE: Be sure to decorate the property with [Browsable(true)]
    /// </summary>
    /// <param name="PropertyName">Name of the variable</param>
    /// <param name="bIsBrowsable">Browsable Value</param>
    private void SetBrowsableProperty<T>(string strPropertyName, bool bIsBrowsable)
    {
        // Get the Descriptor's Properties
        PropertyDescriptor theDescriptor = TypeDescriptor.GetProperties(typeof(T))[strPropertyName];

        // Get the Descriptor's "Browsable" Attribute
        BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
        FieldInfo isBrowsable = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

        // Set the Descriptor's "Browsable" Attribute
        isBrowsable.SetValue(theDescriptorBrowsableAttribute, bIsBrowsable);
    }

Vous pouvez ensuite ajouter également une version qui prend une instance:

    /// <summary>
    /// Set the Browsable property.
    /// NOTE: Be sure to decorate the property with [Browsable(true)]
    /// </summary>
    /// <param name="obj">An instance of the object whose property should be modified.</param>
    /// <param name="PropertyName">Name of the variable</param>
    /// <param name="bIsBrowsable">Browsable Value</param>
    private void SetBrowsableProperty<T>(T obj, string strPropertyName, bool bIsBrowsable)
    {
        SetBrowsableProperty<T>(strPropertyName, bIsBrowsable);
    }

Utilisation:

    class Foo
    {
        [Browsable(false)]
        public string Bar { get; set; }
    }
    void Example()
    {
        SetBrowsableProperty<Foo>("Bar", true);
        Foo foo = new Foo();
        SetBrowsableProperty(foo, "Bar", false);
    }

Je suis tombé sur ce à la recherche d'un moyen de déclarer certains membres visibles ou cachés dans IntelliSense et être en mesure de le changer une fois pour tout ce qui devait être caché au moment de la compilation. Je ne peux pas dire si c'est ce que vous recherchez ou non, mais je l'ai trouvé une réponse à ma question ... pensé qu'il ne pouvait pas faire du mal à partager.

Je mis un symbole de compilation conditionnelle (dans l'onglet Construire des propriétés du projet) IS_VIS (valeur étant vrai si vous voulez que certains membres de montrer, faux si vous souhaitez les cacher) puis:

#if IS_VIS
    public const System.ComponentModel.EditorBrowsableState isVis =
        ComponentModel.EditorBrowsableState.Always;
#else
    public const System.ComponentModel.EditorBrowsableState isVis =
        ComponentModel.EditorBrowsableState.Never;
#endif

vous faites référence à la variable isVis dans l'attribut:

[EditorBrowsable(isVis)]
public string myMethod...

Je l'ai fait en VB et cela a été vite converti en c #. Si quelque chose ne fonctionne pas bien, laissez-moi savoir.

La solution de John Cummings essentiellement travaillé pour moi, mais avait les deux problèmes suivants en raison de son introduction du Generics (qui était bien assez intelligent):

1- la SetBrowsableProperty<T>(T obj, string strPropertyName, bool bIsBrowsable) version échouera quand une collection est passée comme paramètre obj car T, dans ce cas, sera une mise en œuvre de IEnumerable (par exemple liste, tableau, etc.) et non le type de la collection qui était en fait prévu.

2- Il permet de passer dans les types primitifs et qui ne sert à rien dans ce cas et presque toujours l'échec.

Solution complète révisée:

Voici donc la solution révisée qui aborde ces problèmes et a travaillé pour moi: (Je l'ai légèrement renomme les méthodes et les variables)

Tout d'abord la méthode actuelle qui fait le travail principal de modifier la valeur de l'attribut Browsable:

/// <summary>
/// Sets the Browsable attribute value of a property of a non premitive type.
/// NOTE: The class property must be decorated with [Browsable(...)] attribute.
/// </summary>
/// <param name="type">The type that contains the property, of which the Browsable attribute value needs to be changed</param>
/// <param name="propertyName">Name of the type property, of which the Browsable attribute value needs to be changed</param>
/// <param name="isBrowsable">The new Browsable value</param>
public static void SetBrowsableAttributeOfAProperty(Type type, string propertyName, bool isBrowsable)
{
    //Validate type - disallow primitive types (this will eliminate problem-2 as mentioned above)
    if (type.IsEnum || BuiltInTypes.Contains(type))
        throw new Exception($"The type '{type.Name}' is not supported");

    var objPropertyInfo = TypeDescriptor.GetProperties(type);

    // Get the Descriptor's Properties
    PropertyDescriptor theDescriptor = objPropertyInfo[propertyName];

    if (theDescriptor == null)
        throw new Exception($"The property '{propertyName}' is not found in the Type '{type}'");

    // Get the Descriptor's "Browsable" Attribute
    BrowsableAttribute theDescriptorBrowsableAttribute = (BrowsableAttribute)theDescriptor.Attributes[typeof(BrowsableAttribute)];
    FieldInfo browsablility = theDescriptorBrowsableAttribute.GetType().GetField("Browsable", BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

    // Set the Descriptor's "Browsable" Attribute
    browsablility.SetValue(theDescriptorBrowsableAttribute, isBrowsable);
}

Maintenant, la variante proposée dans la solution de John Cummings avec <T>:

public static void SetBrowsableAttributeOfAProperty<T>(string propertyName, bool isBrowsable)
{
    SetBrowsableAttributeOfAProperty(typeof(T), propertyName, isBrowsable);
}

Maintenant, la surcharge qui avait le problème non. 1, mais les poignées de modification suivantes maintenant:

/// <summary>
/// Sets the Browsable attribute value of a property of a non premitive type.
/// NOTE: The class property must be decorated with [Browsable(...)] attribute.
/// </summary>
/// <param name="obj">An instance of the type that contains the property, of which the Browsable attribute value needs to be changed.</param>
/// <param name="propertyName">Name of the type property, of which the Browsable attribute value needs to be changed</param>
/// <param name="isBrowsable">Browsable Value</param>
public static void SetBrowsableAttributeOfAProperty<T>(T obj, string propertyName, bool isBrowsable)
{
    if (typeof(T).GetInterface("IEnumerable") != null && typeof(T) != typeof(string))   //String type needs to be filtered out as String also implements IEnumerable<char> but its not a normal collection rather a primitive type
    {
        //Get the element type of the IEnumerable collection
        Type objType = obj.GetType().GetGenericArguments()?.FirstOrDefault();       //when T is a collection that implements IEnumerable except Array
        if (objType == null) objType = obj.GetType().GetElementType();              //when T is an Array

        SetBrowsableAttributeOfAProperty(objType, propertyName, isBrowsable);
    }
    else
        SetBrowsableAttributeOfAProperty(typeof(T), propertyName, isBrowsable);

et est fonction d'utilité ici pour obtenir tout système C # types intégrés (primitifs):

    public static List<Type> BuiltInTypes
        {
            get
            {
                if (builtInTypes == null)                
                    builtInTypes = Enum.GetValues(typeof(TypeCode)).Cast<TypeCode>().Select(t => Type.GetType("System." + Enum.GetName(typeof(TypeCode), t)))
                                   .ToList();

                return builtInTypes;
            }
        }

Utilisation:

 class Foo
{
    [Browsable(false)]
    public string Bar { get; set; }
}
void Example()
{
    SetBrowsableAttributeOfAProperty<Foo>("Bar", true);     //works

    Foo foo = new Foo();
    SetBrowsableAttributeOfAProperty(foo, "Bar", false);    //works

    List<Foo> foos = new List<Foo> { foo, new Foo { Bar = "item2" } };
    SetBrowsableAttributeOfAProperty(foos, "Bar", true);    //works now, whereas it would crash with an exception in John Cummings's solution
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top