Как я могу использовать обнуляемые типы в конструкторе Winforms? - PullRequest
1 голос
/ 10 января 2012

У меня есть элемент управления с минимальным / максимальным размером. Это ограничение представлено структурой с двумя обнуляемыми свойствами (ноль означает без ограничений). Из-за жизни я не могу заставить дизайнера WinForms принять это.

Я попробовал TypeConvertor (из сети и скопировал из источника .NET 4), и я получаю

"Генерация кода для типа« BoxRange »завершилась неудачно. Ошибка:« указанное приведение неверно. »«

или

"Тип" BoxRange "нельзя привести к типу" BoxRange. ""

и затем он забывает установленные значения. Что я тут не так делаю?

Хотя этот пример взят из примера Size3DConverter, он очень мало отличается от SizeConverter .NET4. Я понятия не имею, почему он не может разделить "#, #" так, как это происходит со структурой размера или точки.

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

1 Ответ

0 голосов
/ 11 января 2012

Я переделал вашу структуру 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);
  }
}
...