C# winforms:将可空类型绑定到其他属性(不是文本)时出错

Posted

技术标签:

【中文标题】C# winforms:将可空类型绑定到其他属性(不是文本)时出错【英文标题】:C# winforms: Error when binding nullable type to other property (not Text) 【发布时间】:2013-11-23 07:06:08 【问题描述】:

我制作了一个自定义文本框,它将(可为空的)十进制值显示为时间 (2.5 = 2:30)。我添加了一个属性“十进制?十进制值”,我将数据源绑定到该属性。这一切都很好,除非我清除文本框以使值为空。

它说“System.String 类型的对象无法转换为 System.Nullable`1[System.Decimal]”。

我看到的是 base.OnValidating 使得 e.Cancel = True。因此,在下方某处执行了导致此问题的检查。不过我不理解这种行为,因为当我绑定到属性 Text 时,我可以毫无问题地清除文本框,并且正在保存空值。

绑定代码:

this.txtUrenDoorberekenen.DataBindings.Add(new System.Windows.Forms.Binding("DecimalValue", this.bsAutokraanOrderRegel, "Uren", true));

自定义属性:

[Browsable(true), Bindable(true), Category("DSE"), DefaultValue(null), Description("De numerieke waarde")]
public decimal? DecimalValue

    get  return this.GeefNumeriek(this.Text); 
    set  this.Text = this.GeefTijd(value); 

this.GeefNumeriek 返回一个小数? (它将文本框的文本转换为可以为空的小数)。 this.GeefTijd(value) 将可以为空的十进制转换为字符串格式。

    private decimal? GeefNumeriek(string waarde)
    
        decimal? result = null;
        if (!String.IsNullOrEmpty(waarde)) 
            try 
                // voeg dubbele punt toe, indien deze ontbreekt
                if (waarde.Length == 1 && waarde.IndexOf(":") < 0)  waarde = waarde + ":00"; 
                if (waarde.Length == 2 && waarde.IndexOf(":") < 0)  waarde = waarde + ":00"; 
                if (waarde.Length >= 3 && waarde.IndexOf(":") < 0)  waarde = waarde.Substring(0, waarde.Length - 2) + ":" + waarde.Substring(waarde.Length - 2); 

                // Uren gedeelte
                result = Convert.ToDecimal(waarde.Substring(0, waarde.IndexOf(":")));

                // Minuten
                int minuten = Convert.ToInt16(waarde.Substring(waarde.IndexOf(":") + 1));
                // Minuten kan niet meer dan 60 zijn
                if (minuten > 60)  throw new Exception(DSETextResource.GeefText("Validatie_Numeriek_Ongeldig")); 

                result = result + ((decimal)minuten / (decimal)60);
            
            catch 
            
        
        return result;
    

【问题讨论】:

这应该回答你的问题:***.com/a/3524691/1073107 Best way to databind a Winforms control to a nullable type?的可能重复 不,它没有。在那个问题中,绑定在属性 Text 上,它确实有效。我想绑定到我自己的自定义属性。 【参考方案1】:

您必须向BindingParse 事件添加一些代码,如下所示:

Binding bind = new Binding("Text", yourObject, "DecimalProperty");
bind.Parse += (s,e) => 
  if((string)e.Value == "") e.Value = default(decimal?);
  else e.Value = decimal.Parse((string)e.Value);
;
textBox1.DataBindings.Add(bind);

注意:上面的代码假设字符串总是可以解析为decimal

【讨论】:

我绑定到另一个属性,因为 Text 无法解析为十进制。绑定到Text没有问题。仅当绑定到另一个(自定义)属性并且值为 null 时。在清除文本框时,在控件中加载空值时都会出错。 @RolandDeschain 另一个自定义属性的类型是什么?看起来你不想回答。我在winforms中使用Binding相当多,几乎可以使用ParseFormat解决问题。 是十进制的? (可为空的十进制)。当然,我想要一个答案。 ;-) @RolandDeschain 太混乱了,你应该发布你的代码来展示你如何绑定你的控件,它不是Text,但它的类型是string(我从异常消息中得出这个),所以它仍然适用(只需更改属性名称)。 我想出了一个使用您的答案的解决方案。

以上是关于C# winforms:将可空类型绑定到其他属性(不是文本)时出错的主要内容,如果未能解决你的问题,请参考以下文章

将可空引用类型转换为不可空引用类型,不那么冗长

如何将可空类型隐式转换为不可空类型

c#中Winform控件的数据源的填充方式,也就是DataSource的类型有几种?

c#如何将可空DateTime以yyyy/MM/dd格式转化为string,就是数据库读取DateTime?显示出来日期不显示时间

将可空值从 Activity 传递到 Fragment

Entity Framework Core:将可空列迁移到必需时的默认值