views:

449

answers:

2

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.

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

StringConverter class:

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;
    }
}
A: 

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?

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);
        }
    }
}
Marc Gravell
+1  A: 

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 { /* ... */ }
Marc Gravell
That seems to do it, thanks! I was thinking I could use BOTH a UITypeEditor and a TypeConverter.
Robert Massa
@Robert - you still can ;-p Don't forget some other controls (`DataGridView` etc) will only use the converter, not the editor.
Marc Gravell