Domanda

sto tweaking un'applicazione WinForms. Questa applicazione ha un Form che contiene un PropertyGrid. Un oggetto viene assegnato alla proprietà SelectedObject modo che la griglia proprietà visualizza le proprietà dell'oggetto.

Il tipo di oggetto assegnato presenta una proprietà che trasporta un EditorAttribute specificando un UITypeEditor.

Questa implementazione dei rendimenti UITypeEditor UITypeEditorEditStyle.Drop nella sua override metodo GetEditStyle. Il suo metodo EditValue visualizza una ListBox da cui può essere assegnato un valore per la proprietà di istanza.

Tutto bene un bene finora.

Ora ho un ulteriore requisito che prevede le voci disponibili nella lista per essere modificati sulla base di altro stato tenuto dal Form che ospita il PropertyGrid. Non riesco a capire come ottenere questo informazioni contestuali al metodo EditValue.

Non sembra essere nulla sul parametro context anche se cerco il cast ai tipi più specifici. Né posso lavorare come aggiungere qualche altro servizio per recuperare dal provider.

Tutte le idee?

È stato utile?

Soluzione

Mi chiedo se ciò che si sta cercando di fare sarebbe sarebbe meglio come TypeConverter tramite GetStandardValues? Ma in entrambi i casi, sia context.Instance e context.PropertyDescriptor sembrano per essere organizzati in un test rapido (per entrambi 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()
                }
            }
        });
    }
}

O come un tipo di convertitore:

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

Altri suggerimenti

Io ero in una situazione simile, ho voluto iniettare un oggetto in costruttore di mio UITypeEditor personalizzato.

Ho seguito Nicolas Cadilhac commento a Qui , dargli tutto il merito. Esso utilizza TypeDescriptionProvider.

Questa è la serie completa di codice.

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

Nel metodo EditValue override, context.Container fornirà l'oggetto che l'editor appartiene. La proprietà context.Container.Components elencherà tutti i controlli che comprende la forma e tutti i suoi figli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top