3

I have a control that I subclass from Label (as an example) and add a custom property to it. I have a custom editor that allows me to pick an object of a custom type. The custom type is attributed with the converter and and editor. Editing works fine - I click in my property cell in the VS designer property grid and the ellipsis displays. I click that and I get my custom form displaying my list to choose from. I make a selection and that selection shows up in my property grid. All good. However, I can not seem to clear that value by backspacing over it like I can with most properties. And more importantly, as soon as I build the project the property value disappears. Before I build, I can go from control to control and the value is set properly, but as soon as I build (or save and close the form) the property loses its value. My custom control looks like this:

public class MyLabel : Label
{
    private MyAlias _alias;

    public MyAlias Alias
    {
        get
        {
            return _alias;
        }
        set
        {
            if (_alias != value)
            {
                _alias = value;
            }
        }
    }
}

The custom type:

[System.ComponentModel.TypeConverter(typeof(MyConverter))]
[System.ComponentModel.Editor(MyTypeEditor, System.Drawing.Design.UITypeEditor)]
public class MyAlias
{
    private string _aliasName;

    public string AliasName
    {
        get
        {
            return _aliasName;
        }
        set
        {
            if (_aliasName != value)
            {
                _aliasName = value;
            }
        }
    }

    public MyAlias(string aliasName)
    {
        if (aliasName == null)
        {
            return;
        }

        _aliasName = aliasName;
    }

    public override string ToString()
    {
        return _aliasName;
    }
}

Custom converter:

public class MyConverter : 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 (!(value is string))
        {
            return base.ConvertFrom(context, culture, value);
        }

        return new MyAlias((string)value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == null)
        {
            throw new ArgumentNullException("destinationType");
        }

        MyAlias alias = (MyAlias)value;
        return alias.ToString();
    }
}

Custom Editor:

public partial class AliasEditorForm : Form
{
    private object _value;

    public object Value
    {
        get
        {
            return _value;
        }
        set
        {
            if (_value != value)
            {
                _value = value;
            }
        }
    }

    public AliasEditorForm()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // Button does have DialogResult property set to OK
        _value = new MyAlias(...text string from form controls here...);
        this.Close();
    }
}

public class MyTypeEditor : UITypeEditor
{
    protected IWindowsFormsEditorService edSvc = null;

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }

    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        if (null != context && null != context.Instance && null != provider)
        {
            edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (null != edSvc)
            {
                AliasEditorForm form = new AliasEditorForm();
                form.Value = value;
                DialogResult r = edSvc.ShowDialog(form);
                return (DialogResult.OK == r) ? form.Value : value;
            }
        }
        return value;
    }
}

It's been a long time since I've worked in WinForms and I never really did much dabbling with design-time stuff so forgive me if I've done something terribly stupid. If I didn't provide enough info, let me know. Thanks in advance!

EDIT: I notice it is not generating the code for the property in the form.Designer.cs file. Still not sure why...

EDIT: Changed the code for the type converter. I can now clear the property by backspacing. I still can't get the designer to generate the code to preserve the property value.

Dennis

Dennis
  • 215
  • 1
  • 3
  • 14
  • This answer might be useful http://stackoverflow.com/a/15803/788 – Matt Nelson Aug 05 '14 at 19:49
  • Thanks for the reply Matt! Unfortunately, I did try that attribute and it did not work. I tried setting the value to Content and also tried setting it to Visible. Neither value solved the problem (and Content actually made it worse by giving me an error on controls where I did not set an Alias value). – Dennis Aug 06 '14 at 12:55
  • 1
    Did you ever figured this out ? I have a simular problem here. My custom control has a public property of List. In designer it opens the standard list editor and when I add some strings here it works fine, but when the custom control (still in designtime, not runtime !) fills some strings in code, than these strings never make it to the designer.cs file, even while they are visible in design time in the property window... – GuidoG Jan 05 '15 at 20:53

0 Answers0