Pergunta

Estou ajustando um aplicativo Winforms. Este aplicativo tem um Form que contém a PropertyGrid. Um objeto é atribuído ao SelectedObject Propriedade para que a grade da propriedade exiba as propriedades do objeto.

O tipo de objeto designado possui uma propriedade que carrega um EditorAttribute especificando a UITypeEditor.

Esta implementação de UITypeEditor retorna UITypeEditorEditStyle.Drop em sua substituição de GetEditStyle método. Seu EditValue O método exibe a ListBox a partir do qual um valor para a propriedade da instância pode ser atribuído.

Tudo bem, um bom até agora.

Agora eu tenho um requisito adicional que exige que os itens disponíveis na lista sejam modificados com base em outro estado mantido pelo Form hospedando o PropertyGrid. Não consigo descobrir como obter essas informações contextuais para o EditValue método.

Não parece haver nada no context Parâmetro Mesmo se eu tentar lançá -lo em tipos mais específicos. Nem posso descobrir como adicionar outro serviço para recuperar do provider.

Alguma ideia?

Foi útil?

Solução

Eu me pergunto se o que você está tentando fazer seria melhor como um TypeConverter através da GetStandardValues? Mas de qualquer maneira, ambos context.Instance e context.PropertyDescriptor parecer ser preenchido em um teste rápido (para ambos GetEditStyle e EditValue):

using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
class MyData
{
    [Editor(typeof(MyEditor), typeof(UITypeEditor))]
    public string Bar { get; set; }

    public string[] Options { get; set; }
}
class MyEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        // break point here; inspect context
        return UITypeEditorEditStyle.DropDown;
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        // break point here; inspect context
        return base.EditValue(context, provider, value);
    }

}
class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form
        {
            Controls =
            {
                new PropertyGrid {
                    Dock = DockStyle.Fill,
                    SelectedObject = new MyData()
                }
            }
        });
    }
}

Ou como um conversor de tipo:

using System;
using System.ComponentModel;
using System.Windows.Forms;

class MyData
{
    [TypeConverter(typeof(MyConverter))]
    public string Bar { get; set; }

    public string[] Options { get; set; }
}
class MyConverter : StringConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        MyData data = (MyData)context.Instance;
        if(data == null || data.Options == null) {
            return new StandardValuesCollection(new string[0]);
        }
        return new StandardValuesCollection(data.Options);
    }
}
class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form
        {
            Controls =
            {
                new PropertyGrid {
                    Dock = DockStyle.Fill,
                    SelectedObject = new MyData()
                }
            }
        });
    }
}

Outras dicas

Eu estava em situação semelhante, queria injetar um objeto no construtor do meu UityPeeditor personalizado.

Eu segui o comentário de Nicolas Cadilhac em Aqui, Dê a ele todo o crédito. Ele usa o TypeDescriptionProvider.

Aqui está o conjunto completo de código.

class Foo
{
    public Foo() { Bar = new Bar(); }
    public Bar Bar { get; set; }
}

class Bar
{
    public string Value { get; set; }
}

class BarTypeDescriptionProvider : TypeDescriptionProvider
{
    private TypeDescriptionProvider _baseProvider;
    string _extraParam;

    public BarTypeDescriptionProvider(Type t, string extraParam)
    {
        this._extraParam = extraParam;
        _baseProvider = TypeDescriptor.GetProvider(t);
    }

    public string ExtraParam
    { 
        get { return _extraParam; } 
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new BarTypeDescriptor(this, _baseProvider.GetTypeDescriptor(objectType, instance), objectType);
    }
}


class BarTypeDescriptor : CustomTypeDescriptor
{
    private Type _objectType;
    private BarTypeDescriptionProvider _provider;

    public BarTypeDescriptor(BarTypeDescriptionProvider provider,  ICustomTypeDescriptor descriptor, Type objectType): base(descriptor)
    {
        if (provider == null) throw new ArgumentNullException("provider");
        if (descriptor == null)
            throw new ArgumentNullException("descriptor");
        if (objectType == null)
            throw new ArgumentNullException("objectType");
        _objectType = objectType;
        _provider = provider;
    }

    public override object GetEditor(Type editorBaseType)
    {
        return new BarEditor(_provider.ExtraParam);
    }
}


class BarEditor : UITypeEditor
{
    private string _extraParam;
    public BarEditor(string x)
        : base()
    {
        _extraParam = x;
    }

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        MessageBox.Show(_extraParam);
        return base.EditValue(context, provider, value);
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        string extraParam = "Extra param from main form";

        TypeDescriptor.AddProvider(new BarTypeDescriptionProvider(typeof(Bar), extraParam), typeof(Bar));

        this.propertyGrid1.SelectedObject = new Foo();
    }
}

Michael

No método de editValue substituído, context.Container fornecerá o objeto ao qual o editor pertence. o context.Container.Components A propriedade listará todos os controles que incluem o formulário e todos os seus filhos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top