I'm tweaking a WinForms application. This application has a Form
that contains a PropertyGrid
. An object is assigned to the SelectedObject
property so that the property grid displays the properties for the object.
The type of the object assigned has a property that carries an EditorAttribute
specifying a UITypeEditor
.
This implementation of UITypeEditor
returns UITypeEditorEditStyle.Drop
in its override of GetEditStyle
method. Its EditValue
method displays a ListBox
from which a value for the instance property can be assigned.
All well an good so far.
Now I have an additional requirement which calls for the available items in the list to be modified based on other state held by the Form
hosting the PropertyGrid
. I can't work out how to get this contextual information to the EditValue
method.
There doesn't seem to be anything on the context
parameter even if I try casting it to more specific types. Neither can I work out how to add some other Service to retrieve from the provider
.
Any ideas?
I wonder if what you are trying to do would would better as a TypeConverter
via GetStandardValues
? But either way, both context.Instance
and context.PropertyDescriptor
seem to be populated in a quick test (for both GetEditStyle
and 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()
}
}
});
}
}
Or as a type-converter:
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()
}
}
});
}
}