Cómo modificar PropertyGrid en tiempo de ejecución (agregar / eliminar propiedades y tipos / enumeraciones dinámicos)

StackOverflow https://stackoverflow.com/questions/313822

Pregunta

¿Cómo se modifica una cuadrícula de propiedades en tiempo de ejecución en todos los sentidos? Quiero poder agregar y eliminar propiedades y agregar `` tipos dinámicos '', lo que quiero decir con eso es un tipo que da como resultado un menú desplegable generado en tiempo de ejecución en la cuadrícula de propiedades usando un TypeConverter.

Realmente he podido hacer ambas cosas (agregar / quitar propiedades y agregar tipo dinámico) pero solo por separado, no al mismo tiempo.

Para implementar el soporte para agregar y eliminar propiedades en tiempo de ejecución, utilicé esto codeproject article y modificó el código un poco para admitir diferentes tipos (no solo cadenas).

private System.Windows.Forms.PropertyGrid propertyGrid1;
private CustomClass myProperties = new CustomClass();

public Form1()
{
    InitializeComponent();

    myProperties.Add(new CustomProperty("Name", "Sven", typeof(string), false, true));
    myProperties.Add(new CustomProperty("MyBool", "True", typeof(bool), false, true));
    myProperties.Add(new CustomProperty("CaptionPosition", "Top", typeof(CaptionPosition), false, true));
    myProperties.Add(new CustomProperty("Custom", "", typeof(StatesList), false, true)); //<-- doesn't work
}

/// <summary>
/// CustomClass (Which is binding to property grid)
/// </summary>
public class CustomClass: CollectionBase,ICustomTypeDescriptor
{
    /// <summary>
    /// Add CustomProperty to Collectionbase List
    /// </summary>
    /// <param name="Value"></param>
    public void Add(CustomProperty Value)
    {
        base.List.Add(Value);
    }

    /// <summary>
    /// Remove item from List
    /// </summary>
    /// <param name="Name"></param>
    public void Remove(string Name)
    {
        foreach(CustomProperty prop in base.List)
        {
            if(prop.Name == Name)
            {
                base.List.Remove(prop);
                return;
            }
        }
    }

etc ...

public enum CaptionPosition
{
    Top,
    Left
}

Mi solución completa se puede descargar aquí .

Funciona bien cuando agrego cadenas, bools o enumeraciones, pero cuando trato de agregar un " tipo dinámico " como StatesList no funciona. ¿Alguien sabe por qué y puede ayudarme a resolverlo?

public class StatesList : System.ComponentModel.StringConverter
{
    private string[] _States = { "Alabama", "Alaska", "Arizona", "Arkansas" };

    public override System.ComponentModel.TypeConverter.StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(_States);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        return true;
    }
}

El método de usar un TypeConverter funciona bien cuando no intenta agregar la propiedad en tiempo de ejecución, por ejemplo este código funciona sin ningún problema, pero quiero poder hacer ambas cosas.

Por favor, eche un vistazo a mi proyecto . Gracias!

¿Fue útil?

Solución

Lo que haces es agregar StatesList (un TypeConverter) como una propiedad.
Lo que debe hacer es agregar una propiedad con StatesList como TypeConverter.

Otros consejos

¡Ah, por supuesto!

myProperties.Add(new CustomProperty("Custom", "", typeof(States), false, true));

[TypeConverter(typeof(StatesList))]
public class States
{
}

Funciona como un encanto, ¡gracias!

He actualizado mi proyecto, espero que pueda ser útil para otros, se puede encontrar aquí .

Esta pregunta y respuesta fue de gran utilidad para mí. Sin embargo, necesitaba extender un poco más las cosas permitiendo valores de lista desplegables generados en tiempo de ejecución. Pensé que publicaría un código de muestra con respecto a lo que requería, en caso de que alguien lo encontrara útil.

Primero, agregué un parámetro de opciones al constructor CustomProperty y agregué una propiedad de Opciones:

    private List<string> lOptions;

    public CustomProperty(string sName, object value, Type tType, bool bReadOnly, bool bVisible, List<string> lOptions)
    {
        this.lOptions = lOptions;
    }

    public List<string> Options
    {
        get { return lOptions; }
    }

Segundo, agregué una propiedad de Opciones a la clase CustomPropertyDescriptor:

    public List<string> Options
    {
        get
        {
            return m_Property.Options;
        }
    }

Tercero, tuve que modificar el método GetStandardValues ??en mi clase de tipo dinámico (es decir, StatesList) para hacer uso de la nueva propiedad Opciones en el objeto CustomPropertyDescriptor:

    public override StandardValuesCollection
                 GetStandardValues(ITypeDescriptorContext context)
    {
        CustomPropertyDescriptor descriptor = (CustomPropertyDescriptor)context.PropertyDescriptor;
        return new StandardValuesCollection(descriptor.Options);
    }

Finalmente, tuve que pasar mi lista de opciones al crear un nuevo objeto CustomProperty:

    List<string> optionsList = new List<string>(new string[] { "test1", "test2", "test3" });        
    CustomProperty myProperty = new CustomProperty(attr.Name, attr.Value, valueType, false, true, optionsList);

En lugar de la lista estática que pasé para este ejemplo, puede generar la lista de opciones para su menú desplegable de la manera que desee, dándole un control total sobre las opciones disponibles.

en mi caso TypeConverter no se aplicaba a la clase de estados

[TypeConverter(typeof(StatesList))] // not work
public class States
{
}

así que agregué override en CustomPropertyDescriptor

public override TypeConverter Converter
{
    get {
        if (this.PropertyType.Equals(typeof(States)) ) {
            return new StatesList(); ; 
        }
        return base.Converter;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top