Доступ к дополнительным контекстным данным в EditValue of UityPeeditor

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

Вопрос

Я настраиваю приложение Winforms. Это приложение имеет Form это содержит PropertyGrid. Анкет Объект назначен SelectedObject свойство так, чтобы сетка свойств отображает свойства для объекта.

Тип назначенного объекта имеет свойство, которое несет EditorAttribute Указание UITypeEditor.

Эта реализация UITypeEditor возврат UITypeEditorEditStyle.Drop в своем переопределении GetEditStyle метод Его EditValue Метод отображает ListBox из которого может быть назначено значение для свойства экземпляра.

Пока все хорошо.

Теперь у меня есть дополнительное требование, которое требует изменения доступных элементов в списке на основе другого состояния, принадлежащего Form Хостинг PropertyGrid. Анкет Я не могу понять, как получить эту контекстную информацию в EditValue метод

Кажется, в context Параметр, даже если я попробую поднять его на более конкретные типы. Я также не могу понять, как добавить другой сервис, чтобы получить из provider.

Любые идеи?

Это было полезно?

Решение

Интересно, будет ли то, что вы пытаетесь сделать, будет лучше как TypeConverter с помощью GetStandardValues? Но в любом случае оба context.Instance а также context.PropertyDescriptor казаться быть заполненным в быстром тесте (для обоих GetEditStyle а также 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()
                }
            }
        });
    }
}

Или как конвертер типа:

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

Другие советы

Я был в аналогичной ситуации, я хотел ввести объект в мой пользовательский конструктор UityPeeditor.

Я последовал за комментарием Николаса Кадильхака в Здесь, Дайте ему все кредит. Он использует TypedEscriptionProvider.

Вот полный набор кода.

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

Майкл

В методе переопределенного редактирования, context.Container предоставит объект, к которому принадлежит редактор. А context.Container.Components Собственность перечисляет все элементы управления, которые включают форму и всех ее детей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top