Property grid item and DoubleClick
.net, c#, propertygrid, type-conversion, winforms
Solution
Your GetStandardValues() method is wrong. It must return the property type, not strings:
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
StandardValuesCollection ret;
Type tpProperty = context.PropertyDescriptor.PropertyType;
if (tpProperty == typeof(bool))
ret = new StandardValuesCollection(new object[] { true, false });
else if (tpProperty == typeof(bool?))
ret = new StandardValuesCollection(new object[] { true, false, null });
else
ret = new StandardValuesCollection(new object[0]);
return ret;
}
Problem
I'm using PropertyGrid control for editing some objects in my application. I'm using custom TypeConverters and TypeEditors for better user interface. I have problem with custom TypeConverter for boolean properties. If I have this class: ``` public class MyClass { public string Name { get; set; } [System.ComponentModel.TypeConverter( typeof( BoolTypeConverter ) )] public bool Flag { get; set; } } ``` and I create instance and set it as SelectedObject in PropertyGrid - all is fine until the user DoubleClicked on property grid item form "Flag" property. After DoubleClick is raised this message: (source: tcks.wz.cz) The TypeConverter class looks: ``` public class BoolTypeConverter : System.ComponentModel.TypeConverter { public const string TEXT_TRUE = "On"; public const string TEXT_FALSE = "Off"; public const string TEXT_NONE = "< none >"; public override object CreateInstance( System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues ) { object ret = base.CreateInstance( context, propertyValues ); return ret; } public override bool GetCreateInstanceSupported( System.ComponentModel.ITypeDescriptorContext context ) { bool ret = base.GetCreateInstanceSupported( context ); return ret; } public override bool IsValid( System.ComponentModel.ITypeDescriptorContext context, object value ) { bool ret; if ( value is string ) { string tmpValue = value.ToString().Trim(); if ( string.Compare( tmpValue, TEXT_NONE, StringComparison.InvariantCultureIgnoreCase ) == 0 ) { ret = true; } else if ( string.Compare( tmpValue, TEXT_TRUE, StringComparison.InvariantCultureIgnoreCase ) == 0 ) { ret = true; } else if ( string.Compare( tmpValue, TEXT_FALSE, StringComparison.InvariantCultureIgnoreCase ) == 0 ) { ret = true; } else { bool blValue; ret = bool.TryParse( tmpValue, out blValue ); } } else { ret = base.IsValid( context, value ); } return ret; } public override bool CanConvertFrom( System.ComponentModel.ITypeDescriptorContext context, Type sourceType ) { bool ret = false; if ( sourceType == typeof( string ) ) { ret = true; } else { ret = base.CanConvertFrom( context, sourceType ); } return ret; } public override object ConvertFrom( System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value ) { object ret = null; bool converted = false; if ( value is string ) { string tmpValue = value.ToString().Trim(); if ( string.Compare( tmpValue, TEXT_NONE, StringComparison.InvariantCultureIgnoreCase ) == 0 || string.IsNullOrEmpty( tmpValue ) ) { ret = null; converted = true; } else if ( string.Compare( tmpValue, TEXT_TRUE, StringComparison.InvariantCultureIgnoreCase ) == 0 ) { ret = true; converted = true; } else if ( string.Compare( tmpValue, TEXT_FALSE, StringComparison.InvariantCultureIgnoreCase ) == 0 ) { ret = false; converted = true; } else { bool blValue; if ( converted = bool.TryParse( tmpValue, out blValue ) ) { ret = blValue; } } } if ( false == converted ) { ret = base.ConvertFrom( context, culture, value ); } return ret; } public override bool CanConvertTo( System.ComponentModel.ITypeDescriptorContext context, Type destinationType ) { bool ret = false; if ( destinationType == typeof( bool ) ) { ret = true; } else { ret = base.CanConvertTo( context, destinationType ); } return ret; } public override object ConvertTo( System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType ) { object ret = null; bool converted = false; if ( destinationType == typeof( string ) ) { if ( null == value ) { ret = TEXT_NONE; converted = true; } else if ( value is bool? || value is bool ) { if ( (bool)value ) { ret = TEXT_TRUE; } else { ret = TEXT_FALSE; } converted = true; } else if ( value is string ) { ret = value; converted = true; } } if ( false == converted ) { ret = base.ConvertTo( context, culture, value, destinationType ); } return ret; } public override StandardValuesCollection GetStandardValues( System.ComponentModel.ITypeDescriptorContext context ) { StandardValuesCollection ret; Type tpProperty = context.PropertyDescriptor.PropertyType; if ( tpProperty == typeof( bool ) ) { ret = new StandardValuesCollection( new string[]{ TEXT_TRUE, TEXT_FALSE } ); } else if ( tpProperty == typeof( bool? ) ) { ret = new StandardValuesCollection( new string[]{ TEXT_TRUE, TEXT_FALSE, TEXT_NONE } ); } else { ret = new StandardValuesCollection( new string[0] ); } return ret; } public override bool GetStandardValuesSupported( System.ComponentModel.ITypeDescriptorContext context ) { bool ret; Type tpProperty = context.PropertyDescriptor.PropertyType; if ( tpProperty == typeof( bool ) || tpProperty == typeof( bool? ) ) { ret = true; } else { ret = false; } return ret; } } ``` This behaviour is very confusing for users. How can I prevent it? Thanks