2012-01-10 15 views
1

私は、最小/最大サイズの制約を持つコントロールを持っています。この制約は、2つのnull可能なプロパティを持つ構造体によって表されます(nullは無制限を意味します)。私の人生にとって、私はWinFormsデザイナーにそれを受け入れることはできません。Winformsデザイナーでnull可能な型を使用するにはどうすればよいですか?

私は(ネットからおよび.NET 4のソースからコピーされた)TypeConvertorを試してみましたが、私は

は「タイプ 『BoxRange』のコード生成が失敗します。エラーは、「キャストが有効ではありません指定されたました。」」

または

"タイプ 'BoxRangeはBoxRange' を型にキャストすることはできません ''"

そして、設定された値を忘れてしまいます。私はここで間違って何をしていますか?

この例はSize3DConverterの例ですが、.NET4のSizeConverterとほとんど違いはありません。私はサイズやポイント構造で "#、#"を分割することができない理由が分かりません。

[System.SerializableAttribute()] 
[System.ComponentModel.TypeConverter(typeof(RKSHARP2.Designer.SizeRangeConvertor))] 
public struct SizeRange 
{ 
    private System.Byte? Byte_Minimum; 
    private System.Byte? Byte_Maximum; 

    [System.ComponentModel.DefaultValue(typeof(System.Nullable<System.Byte>), null)] 
    public System.Byte? Minimum 
    { 
    get 
    { 
     return this.Byte_Minimum; 
    } 
    set 
    { 
     this.Byte_Minimum = value; 
    } 
    } 

    [System.ComponentModel.DefaultValue(typeof(System.Nullable<System.Byte>),null)] 
    public System.Byte? Maximum 
    { 
    get 
    { 
     return this.Byte_Maximum; 
    } 
    set 
    { 
     this.Byte_Maximum = value; 
    } 
    } 

    public SizeRange (System.Byte? Byte_Minimum, System.Byte? Byte_Maximum) 
    { 
    this.Byte_Minimum = Byte_Minimum; 
    this.Byte_Maximum = Byte_Maximum; 
    } 

    public static System.Boolean operator == (RKSHARP2.Controls.SizeRange Struct_Compare1, RKSHARP2.Controls.SizeRange Struct_Compare2) 
    { 
    return (Struct_Compare1.Minimum == Struct_Compare2.Minimum && Struct_Compare1.Maximum == Struct_Compare2.Maximum); 
    } 

    public static System.Boolean operator != (RKSHARP2.Controls.SizeRange Struct_Compare1, RKSHARP2.Controls.SizeRange Struct_Compare2) 
    { 
    return (Struct_Compare1.Minimum != Struct_Compare2.Minimum || Struct_Compare1.Maximum != Struct_Compare2.Maximum); 
    } 

    public override System.Boolean Equals (System.Object Object_Compare) 
    { 
    if ((Object_Compare is RKSHARP2.Controls.SizeRange) == false) 
    { 
     return false; 
    } 
    else 
    { 
     return ((((RKSHARP2.Controls.SizeRange)(Object_Compare)).Minimum == this.Minimum) && (((RKSHARP2.Controls.SizeRange)(Object_Compare)).Maximum == this.Maximum)); 
    } 
    } 

    public override System.Int32 GetHashCode() 
    { 
    return this.Byte_Minimum.GetValueOrDefault()^this.Byte_Maximum.GetValueOrDefault(); 
    } 

    public override System.String ToString() 
    { 
    return RKSHARP2.Convertor.ToString(this.Minimum, "?") + "," + RKSHARP2.Convertor.ToString(this.Maximum, "?"); 
    } 
} 

public SizeRangeConvertor() 
{ 
    public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) 
    { 
    if (sourceType == typeof(string)) 
     return true; 
    return base.CanConvertFrom(context, sourceType); 
    } 

    public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) 
    { 
    if (destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor)) 
     return true; 
    return base.CanConvertTo(context, destinationType); 
    } 

    public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
    { 
    if (value is string) 
    { 
     if (culture == null) 
     culture = System.Globalization.CultureInfo.InvariantCulture; 
     string sValue = (string)value; 

     if (sValue == null || sValue == string.Empty) 
     sValue = "?,?"; 
     string[] numbers = sValue.Split(new char[] { ',' }); 
     object[] values = null; 
     System.Type[] types = null; 

     if (numbers.Length == 2) 
     { 
     values = new object[numbers.Length]; 
     types = new System.Type[numbers.Length]; 
     for (int i = 0; i < numbers.Length; i++) 
     { 
      values[1] = RKSHARP2.Convertor.ToByte(numbers[i]); 
      types[i] = typeof(byte?); 
     } 
     } 

     if (values != null) 
     { 
     System.Type type = GetSize3DType(context); 
     System.Reflection.ConstructorInfo constructorInfo = type.GetConstructor(types); 
     return constructorInfo.Invoke(values); 
     } 
    } 
    return base.ConvertFrom(context, culture, value); 
    } 

    public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) 
    { 
    System.Type type = value.GetType(); 
    byte? width = RKSHARP2.Convertor.ToByte(type.GetProperty("Minimum").GetValue(value, null)); 
    byte? height = RKSHARP2.Convertor.ToByte(type.GetProperty("Maximum").GetValue(value, null)); 
    if (destinationType == typeof(string)) 
    { 
     if (culture == null) 
     culture = System.Globalization.CultureInfo.InvariantCulture; 
     return string.Format("{0},{1}", width, height); 
    } 
    else if (destinationType == typeof(System.ComponentModel.Design.Serialization.InstanceDescriptor)) 
    { 
     System.Reflection.ConstructorInfo constructorInfo = type.GetConstructor(new System.Type[] { typeof(byte?), typeof(byte?) }); 
     if (constructorInfo != null) 
     return new System.ComponentModel.Design.Serialization.InstanceDescriptor(constructorInfo, new object[] { width, height }); 
    } 
    return base.ConvertTo(context, culture, value, destinationType); 
    } 

    public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) 
    { 
    System.Type type = GetSize3DType(context); 
    System.Reflection.ConstructorInfo constructorInfo = type.GetConstructor(new System.Type[] { typeof(byte?), typeof(byte?) }); 
    return constructorInfo.Invoke(new object[] { 
     propertyValues["Minimum"], 
     propertyValues["Maximum"]}); 
    } 

    public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) 
    { 
    return true; 
    } 

    public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) 
    { 
    System.Type type = GetSize3DType(context); 
    return System.ComponentModel.TypeDescriptor.GetProperties(type, attributes).Sort(new string[] { "Minimum", "Maximum" }); 
    } 

    public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) 
    { 
    return true; 
    } 

    private System.Type GetSize3DType(System.ComponentModel.ITypeDescriptorContext context) 
    { 
    if (context == null) 
     return typeof(RKSHARP2.Controls.SizeRange); 
    return context.PropertyDescriptor.PropertyType; 
    } 
} 
+0

デザイナーはテキストのみを表示できるため、TypeConverterはnull値を空の文字列に変換できる必要があります。あなたのエラーは、そうしていないことを示唆しています。 TypeConverterコードを含めるように質問を編集してみてください。 – LarsTech

答えて

0

下記のSizeRange構造体を再加工しました。

[Serializable()] 
[TypeConverter(typeof(SizeRangeConverter))] 
public struct SizeRange { 
    private Byte? _min; 
    private Byte? _max; 

    public SizeRange(Byte? min, Byte? max) { 
    _min = min; 
    _max = max; 
    } 

    public Byte? Minimum { 
    get { return _min; } 
    set { _min = value; } 
    } 

    public Byte? Maximum { 
    get { return _max; } 
    set { _max = value; } 
    } 

    public override bool Equals(object obj) { 
    if (obj is SizeRange) 
     return ((SizeRange)obj).Minimum == this.Minimum && ((SizeRange)obj).Maximum == this.Maximum; 
    else 
     return false; 
    } 

    public override int GetHashCode() { 
    return this.Minimum.GetValueOrDefault()^this.Maximum.GetValueOrDefault(); 
    } 

    public override string ToString() { 
    string minValue = this.Minimum == null ? "?" : this.Minimum.ToString(); 
    string maxValue = this.Maximum == null ? "?" : this.Maximum.ToString(); 
    return minValue + "," + maxValue; 
    } 

    public static Boolean operator ==(SizeRange sr1, SizeRange sr2) { 
    return (sr1.Minimum == sr2.Minimum && sr1.Maximum == sr2.Maximum); 
    } 

    public static Boolean operator !=(SizeRange sr1, SizeRange sr2) { 
    return !(sr1 == sr2); 
    } 
} 

そして、ここで働く単純なTypeConverterクラスがあります。

public class SizeRangeConverter : 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, CultureInfo culture, object value) { 
    if (value is string) { 
     string[] v = ((string)value).Split(','); 
     Byte? minValue = null; 
     Byte? maxValue = null; 
     Byte minTest; 
     Byte maxTest; 
     if (byte.TryParse(v[0], out minTest)) 
     minValue = minTest; 
     if (byte.TryParse(v[1], out maxTest)) 
     maxValue = maxTest; 

     return new SizeRange(minValue, maxValue); 
    } 
    return base.ConvertFrom(context, culture, value); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { 
    if (destinationType == typeof(string)) 
     return ((SizeRange)value).ToString(); 

    return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 
+0

いいえ、私はまだ "コード生成に失敗しました、指定されたキャストは有効ではありません"と値を忘れてしまいます。 –

+0

@RyanKillianどの行ですか? – LarsTech

+0

私はVisual Studio 2008 FWIWを使用しています。私は行を取得しない、私はちょうどVisual Studioのメッセージボックスを取得する "BoxRangeプロパティのコード生成に失敗しました。エラーが(指定されたキャストが有効ではありません)。それでコンパイルが続けられ、すべてが忘れられます。私のTypeConvertorが関数呼び出しとしてうまく動作したが、デザイナーがそれを窒息させているので、狂っている。 –

関連する問題