propertygrid中的TypeConverter只从字符串转换,而不是转换到字符串

时间:2022-08-23 08:10:34

Only the ConvertTo method gets called(a lot of times) when accessing the propertygrid. This correctly returns the "Foo!" string in the propertygrid. When I click to edit I get an exception Cannot convert object of type Foo to type System.String.(not exactly, translated). The ConvertFrom method doesn't get called, any clues why? And the error indicates it's trying to convert TO a string, not from.

只有在访问propertygrid时才调用ConvertTo方法(很多次)。这将在propertygrid中正确地返回“Foo!”字符串。当我点击编辑时,我得到一个异常不能将Foo类型的对象转换为System.String。(不是翻译)。ConvertFrom方法没有被调用,有什么线索吗?错误表明它试图转换成字符串,而不是从。

I would think when I want to edit this object, it has to convert from Foo to string, and when finished editing back.

我想,当我要编辑这个对象时,它必须从Foo转换为string,当它完成编辑时。

StringConverter class:

StringConverter类:

public class FooTypeConverter : StringConverter {
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
        return new Foo((string) value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
        return "Foo!";
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
        return true;
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
        return true;
    }
}

Property being accessed:

属性被访问:

Foo _foo = new Foo();
[Editor(typeof(System.ComponentModel.Design.MultilineStringEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(FooTypeConverter))]
public Foo Foo {
    get {
        return _foo;
    }
    set {
        _foo = value;
    }
}

2 个解决方案

#1


5  

Re your update; here's a FooEditor that should work as a shim:

是你的更新;这里有一个作为垫片的页脚编辑器:

class FooEditor : UITypeEditor
{
    MultilineStringEditor ed = new MultilineStringEditor();
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        Foo foo = value as Foo;
        if (foo != null)
        {
            value = new Foo((string)ed.EditValue(provider, foo.Value));
        }
        return value;        
    }
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return ed.GetEditStyle();
    }
    public override bool  IsDropDownResizable {
        get { return ed.IsDropDownResizable; }
    }
}

You'll obviously need to associate it:

你显然需要把它联系起来:

[TypeConverter(typeof(FooTypeConverter))]
[Editor(typeof(FooEditor), typeof(UITypeEditor))]
class Foo { /* ... */ }

#2


0  

Cannot reproduce; it works fine for me; you should be testing the destinationType and type of value, btw - but that isn't stopping it calling ConvertFrom. Do you have a complete example (perhaps based on the following) that shows it not calling ConvertFrom?

不能复制;对我来说没问题;顺便说一句,您应该测试destinationType和类型的值,但是这并不能阻止它调用ConvertFrom。您是否有一个完整的示例(可能基于以下内容),显示它不调用ConvertFrom?

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Forms;
public class FooTypeConverter : StringConverter {
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return new Foo("FooTypeConverter.ConvertFrom: " + Convert.ToString(value));
    }
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        return "FooTypeConverter.ConvertTo: " + ((Foo)value).Value;
    }
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return true;
    }
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return true;
    }
}
[TypeConverter(typeof(FooTypeConverter))]
class Foo
{
    public string Value { get; set; }
    public Foo(string value) { Value = value; }

    public override string ToString()
    {
        return "Foo.ToString";
    }
}
class Test
{
    public Foo Foo { get; set; }

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        using(Form form = new Form())
        using (PropertyGrid grid = new PropertyGrid())
        {
            grid.Dock = DockStyle.Fill;
            grid.SelectedObject = new Test { Foo = new Foo("Main") };
            form.Controls.Add(grid);
            Application.Run(form);
        }
    }
}

#1


5  

Re your update; here's a FooEditor that should work as a shim:

是你的更新;这里有一个作为垫片的页脚编辑器:

class FooEditor : UITypeEditor
{
    MultilineStringEditor ed = new MultilineStringEditor();
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        Foo foo = value as Foo;
        if (foo != null)
        {
            value = new Foo((string)ed.EditValue(provider, foo.Value));
        }
        return value;        
    }
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return ed.GetEditStyle();
    }
    public override bool  IsDropDownResizable {
        get { return ed.IsDropDownResizable; }
    }
}

You'll obviously need to associate it:

你显然需要把它联系起来:

[TypeConverter(typeof(FooTypeConverter))]
[Editor(typeof(FooEditor), typeof(UITypeEditor))]
class Foo { /* ... */ }

#2


0  

Cannot reproduce; it works fine for me; you should be testing the destinationType and type of value, btw - but that isn't stopping it calling ConvertFrom. Do you have a complete example (perhaps based on the following) that shows it not calling ConvertFrom?

不能复制;对我来说没问题;顺便说一句,您应该测试destinationType和类型的值,但是这并不能阻止它调用ConvertFrom。您是否有一个完整的示例(可能基于以下内容),显示它不调用ConvertFrom?

using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Forms;
public class FooTypeConverter : StringConverter {
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return new Foo("FooTypeConverter.ConvertFrom: " + Convert.ToString(value));
    }
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        return "FooTypeConverter.ConvertTo: " + ((Foo)value).Value;
    }
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return true;
    }
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return true;
    }
}
[TypeConverter(typeof(FooTypeConverter))]
class Foo
{
    public string Value { get; set; }
    public Foo(string value) { Value = value; }

    public override string ToString()
    {
        return "Foo.ToString";
    }
}
class Test
{
    public Foo Foo { get; set; }

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        using(Form form = new Form())
        using (PropertyGrid grid = new PropertyGrid())
        {
            grid.Dock = DockStyle.Fill;
            grid.SelectedObject = new Test { Foo = new Foo("Main") };
            form.Controls.Add(grid);
            Application.Run(form);
        }
    }
}