.NET PropertyGrid: доступ к экземплярам объектов и управление ими во время выполнения

#c# #.net #winforms #propertygrid

#c# #.net #winforms #сетка свойств

Вопрос:

Я хотел бы получить доступ к object объектам через PropertyGrid и заставить их вести себя так, как они представляют на самом деле. Для игрушечного класса, такого как;

 [TypeConverter(typeof(ObjectBucket.ObjectBucketConverter))]
class ObjectBucket
{
    public object foo;

    [Browsable(true)]
    public object Object
    {
        get { return foo; }
        set { foo = value; }
    }

    private class ObjectBucketConverter : ExpandableObjectConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) ? true : base.CanConvertFrom(context, sourceType);
        }
    }
}
  

я хотел бы иметь возможность установить, скажем, a float через средство доступа к объекту, а затем заставить его вести себя как a float в PropertyGrid, а не стандартное object поведение, заключающееся в возможности ничего с ним не делать.

В качестве обходного пути я ввел следующий метод доступа в;

 [Browsable(true)]
public string ObjectStr
{
    get { return foo.ToString(); }
    set
    {
        try
        {
            foo = TypeDescriptor.GetConverter(foo.GetType()).ConvertFromInvariantString(value);
        }
        catch
        {
            return;
        }
    }
}
  

что позволяет мне манипулировать объектом, но это не идеально. Возможно ли вообще то, что я хочу сделать?

Ответ №1:

Это возможно. Вам необходимо реализовать ICustomTypeDescriptor и предоставить свои собственные экземпляры PropertyDescriptors System.ComponentModel ) — в этих дескрипторах свойств вы можете указать тип свойства — в вашем случае float.

Ответ №2:

Я предлагаю вам реализовать свой собственный редактор типов для ObjectBucket.Свойство объекта. Это позволит вам отобразить форму редактора, в которой пользователь может указать тип и значение для этого свойства следующим образом:
введите описание изображения здесь

Вот скелет реализации:

 class ObjectBucket {
    object foo;
    [Editor(typeof(ObjectUITypeEditor), typeof(UITypeEditor))]
    public object Object {
        get { return foo; }
        set { foo = value; }
    }
}
//...
class ObjectUIEditor : Form {
    public ObjectUIEditor(object editValue) {
        /* TODO Initialize editor*/
    }
    public object EditValue {
        get { return null; /* TODO GetValue from editor */} 
    }
}
//...
class ObjectUITypeEditor : System.Drawing.Design.UITypeEditor {
    System.Windows.Forms.Design.IWindowsFormsEditorService edSvc = null;
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object objValue)
        if(context != null amp;amp; context.Instance != null amp;amp; provider != null) {
            edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if(edSvc != null) {
                try {
                    ObjectUIEditor editor = new ObjectUIEditor(objValue);
                    if(edSvc.ShowDialog(editor) == DialogResult.OK) 
                        objValue = editor.EditValue;
                }
                catch { }
            }
        }
        return objValue;
    }
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
        if(context != null amp;amp; context.Instance != null) 
            return UITypeEditorEditStyle.Modal;
        return base.GetEditStyle(context);
    }
}