Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Winforms designer中使用可空类型?_C#_Winforms_Nullable - Fatal编程技术网

C# 如何在Winforms designer中使用可空类型?

C# 如何在Winforms designer中使用可空类型?,c#,winforms,nullable,C#,Winforms,Nullable,我有一个控件,上面有一个最小/最大大小限制。此约束由具有两个可为null的属性的结构表示。null表示没有限制。就我个人而言,我无法让WinForms设计器接受它 我从网络上尝试了一个类型转换器,并从.NET4源代码复制了它,我得到了 “BoxRange”类型的代码生成失败。错误为“指定的强制转换无效。” 或 无法将类型“BoxRange”强制转换为类型“BoxRange” 然后它会忘记设置的值。我做错了什么 虽然这个示例来自Size3DConverter示例,但它与.NET4的SizeConv

我有一个控件,上面有一个最小/最大大小限制。此约束由具有两个可为null的属性的结构表示。null表示没有限制。就我个人而言,我无法让WinForms设计器接受它

我从网络上尝试了一个类型转换器,并从.NET4源代码复制了它,我得到了

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

我重新设计了下面的SizerAge结构

[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类,它可以工作。它需要更多的验证工作,但对我来说,它在designer中起了作用:

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

设计器只能显示文本,因此TypeConverter必须能够将空值转换为空字符串。您的错误提示它没有这样做。请尝试编辑您的问题以包含TypeConverter代码。不,我仍然无法生成代码,指定的强制转换无效,然后它会忘记值。我使用Visual Studio 2008 FWIW。我没有得到一行,我只是得到一个VisualStudio消息框,其中属性BoxRange的代码生成失败。指定的错误类型转换无效。然后继续编译,它会忘记一切。这太疯狂了,因为我的TypeConverter作为一个函数调用工作得很好,但设计者却被它扼杀了。