Como modificar PropertyGrid em tempo de execução (adicionar / remover propriedades e dinâmicas tipos / enums)

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

Pergunta

Como você modificar um PropertyGrid em tempo de execução em todos os sentidos? Eu quero ser capaz de adicionar e remover e adicionar propriedades "tipos dinâmicos", o que quero dizer com isso é um tipo que resultam em um tempo de execução gerado suspensa na PropertyGrid usando um TypeConverter.

Eu tenho realmente sido capaz de fazer ambas as coisas (adicionar propriedades / remover e adicionar tipo dinâmico), mas apenas separadamente não ao mesmo tempo.

Para implementar o suporte para adicionar e remover propriedades em tempo de execução Eu costumava este codeproject artigo e modificou o código um pouco para suportar tipos diferentes (não apenas strings).

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
}

Meu solução completa pode ser baixado aqui .

Ele funciona muito bem quando eu adiciono cordas, bools ou enums, mas quando eu tento adicionar um "tipo dinâmico" como StatesList ele não funciona. Alguém sabe por que e pode me ajudar a resolvê-lo?

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;
    }
}

O método de usar um TypeConverter funciona bem quando você não tente adicionar a propriedade em tempo de execução, por exemplo, este código obras sem qualquer problema, mas eu quero ser capaz de fazer as duas coisas.

Por favor, dê uma olhada meu projeto . Obrigado!

Foi útil?

Solução

O que você faz, está adicionando StatesList (a TypeConverter) como uma propriedade.
O que você deve fazer, é a adição de uma propriedade com StatesList como seu TypeConverter.

Outras dicas

Ah, claro!

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

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

funciona como um encanto, muito obrigado!

Eu atualizei meu projeto, espero que possa ser útil para outras pessoas, ela pode ser encontrada aqui .

Esta questão resposta foi de grande utilidade para mim. No entanto, eu precisava para prolongar as coisas um pouco mais longe, permitindo tempo de execução gerado suspensa valores da lista. Eu pensei que eu ia postar um código de exemplo em relação ao que era necessário, em alguém acha caso seja útil.

Em primeiro lugar, eu adicionei um parâmetro de opções para o construtor CustomProperty e acrescentou uma propriedade opções:

    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; }
    }

Em segundo lugar, eu adicionei uma propriedade Opções para a classe CustomPropertyDescriptor:

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

Em terceiro lugar, eu tive que modificar o método GetStandardValues ??na minha classe tipo dinâmico (ou seja StatesList) para fazer uso da nova propriedade Opções no objeto CustomPropertyDescriptor:

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

Finalmente, eu tinha que passar na minha lista de opções ao criar um novo 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);

No lugar da lista estática que passei em para este exemplo, você pode gerar a lista de opções para o seu suspensa em qualquer forma que você, por favor, o que lhe dá controle total sobre as opções disponíveis.

no meu caso TypeConverter não se aplicava a classe Unidos

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

Então eu adicionei override em CustomPropertyDescriptor

public override TypeConverter Converter
{
    get {
        if (this.PropertyType.Equals(typeof(States)) ) {
            return new StatesList(); ; 
        }
        return base.Converter;
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top