c# - Cómo modificar PropertyGrid en tiempo de ejecución(agregar/eliminar propiedades y tipos dinámicos/enumeraciones)
.net winforms (4)
¿Cómo se modifica una propiedad cuadrícula 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 que es un tipo que da como resultado un menú desplegable generado en tiempo de ejecución en la propiedad grid usando un TypeConverter.
De hecho, pude hacer ambas cosas (agregar / eliminar propiedades y agregar un 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é este artículo de proyecto de código y modifiqué un poco el código 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 intento 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 utilizar 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!
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í .
Lo que hace es agregar StatesList (TypeConverter) como una propiedad.
Lo que debe hacer es agregar una propiedad con StatesList como TypeConverter.
Esta pregunta y respuesta fue de gran utilidad para mí. Sin embargo, necesitaba extender las cosas un poco más al permitir valores de lista desplegable 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 encuentre útil.
Primero, agregué un parámetro de opciones al constructor CustomProperty y agregué una propiedad Options:
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; }
}
En segundo lugar, agregué una propiedad Options a la clase CustomPropertyDescriptor:
public List<string> Options
{
get
{
return m_Property.Options;
}
}
En tercer lugar, tuve que modificar el método GetStandardValues en mi clase de tipo dinámico (es decir, StatesList) para hacer uso de la nueva propiedad Options en el objeto CustomPropertyDescriptor:
public override StandardValuesCollection
GetStandardValues(ITypeDescriptorContext context)
{
CustomPropertyDescriptor descriptor = (CustomPropertyDescriptor)context.PropertyDescriptor;
return new StandardValuesCollection(descriptor.Options);
}
Finalmente, tuve que pasar en 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, lo que le da control total sobre las opciones disponibles.
en mi caso TypeConverter no se aplicaba a la clase States
[TypeConverter(typeof(StatesList))] // not work
public class States
{
}
así que agregué el reemplazo en CustomPropertyDescriptor
public override TypeConverter Converter
{
get {
if (this.PropertyType.Equals(typeof(States)) ) {
return new StatesList(); ;
}
return base.Converter;
}
}