Custom editors in a property grid that uses Dictionary

北战南征 提交于 2019-12-12 03:35:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!