代码之家  ›  专栏  ›  技术社区  ›  TcKs

属性网格项并双击

  •  6
  • TcKs  · 技术社区  · 16 年前

    我对布尔属性的自定义TypeConverter有问题。如果我有这门课:

    public class MyClass {
        public string Name { get; set; }
    
        [System.ComponentModel.TypeConverter( typeof( BoolTypeConverter ) )]
        public bool Flag { get; set; }
    }
    

    我创建实例并在PropertyGrid中将其设置为SelectedObject—在用户双击属性网格项表单“Flag”属性之前,一切正常。双击后出现此消息: alt text
    (来源: tcks.wz.cz

    TypeConverter类看起来:

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

    这种行为让用户非常困惑。我怎样才能预防呢?

    谢谢

    1 回复  |  直到 7 年前
        1
  •  10
  •   Nicolas Cadilhac    16 年前

    GetStandardValues()方法错误。它必须返回属性类型,而不是字符串:

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