问题
I am using a property grid that uses a dictionary using the adapter found here.
I now need the ability to use a custom editor. More specifically a file chooser. If the object in the dictionary is a string it just uses the default string editor.
Could I implement a new class called FilePath or something that would just act as a wrapper for string but would cause the property grid to use the OpenFileDialog, and display the result as a string in the PropertyGrid once chosen?
Is this possible? And if so how?
回答1:
If you want to have the file path editor in the property grid using the dictionary adapter you have referenced, I would make the FilePath class like you suggest. You will need to also implement two additional classes to make this all work with the property grid: An editor and a type converter.
Let's assume your FilePath object is a simple one:
class FilePath
{
public FilePath(string inPath)
{
Path = inPath;
}
public string Path { get; set; }
}
Your property grid will display the class name in light gray, not very useful. Let's write a TypeConverter to display the string that this class really wraps around
class FilePathConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (IsValid(context, value))
return new FilePath((string)value);
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return destinationType == typeof(string);
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
return ((FilePath)value).Path;
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool IsValid(ITypeDescriptorContext context, object value)
{
if (value.GetType() == typeof(string))
return true;
return base.IsValid(context, value);
}
}
Add the TypeConverter attribute to our FilePath class to convert to and from a string.
[TypeConverter(typeof(FilePathConverter))]
class FilePath
{
...
}
Now the property grid will display the string and not the type name, but you want the ellipsis to bring up a file selection dialog, so we make a UITypeEditor:
class FilePathEditor : UITypeEditor
{
public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
return System.Drawing.Design.UITypeEditorEditStyle.Modal;
}
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
FilePath path = (FilePath)value;
OpenFileDialog openFile = new OpenFileDialog();
openFile.FileName = path.Path;
if (openFile.ShowDialog() == DialogResult.OK)
path.Path = openFile.FileName;
return path;
}
}
Add the Editor attribute to our FilePath class to use the new class:
[TypeConverter(typeof(FilePathConverter))]
[Editor(typeof(FilePathEditor), typeof(UITypeEditor))]
class FilePath
{
...
}
Now you can add FilePath objects to your IDictionary and have them editable through the property grid
IDictionary d = new Dictionary<string, object>();
d["Path"] = new FilePath("C:/");
来源:https://stackoverflow.com/questions/13609292/custom-editors-in-a-property-grid-that-uses-dictionary