这是怎么回事:
1)用户在包含日期的文本框中单击.
2)用户清除日期
3)用户尝试移动到另一个字段,但不能.没有出现错误消息 – 就像验证失败一样.
更多信息:
1)文本框的Text属性绑定到使用数据表作为其源的数据视图.绑定字段是可空的日期时间字段,没有约束或默认值.
2)Validating事件触发,CancelEventArgs属性未设置为Cancel.完成了Validated,LostFocus和Leave事件,LostFocus>离开>证实
3)除了几个例外,我看不到任何与控件或数据源相关的代码更改.首先是这个:
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text",Me.dvClientNos,"RangeEnd"))
现在改为:
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text","RangeEnd",True))
第二是这个:
Me.dcolRangeEnd.DataType = GetType(System.DateTime)
现在改为:
Me.dcolRangeEnd.DataType = GetType(Date)
还有这个,从第一天开始就在代码中:
AddHandler txtRangeEnd.DataBindings("Text").Format,AddressOf FormatBoxToDate Private Sub FormatBoxToDate(ByVal sender As Object,ByVal e As ConvertEventArgs) Try If Not e.Value Is DBNull.Value Then e.Value = Format(e.Value,"d") End If End Try End Sub
现在,如果我从添加数据绑定中删除“,True”,那么我可以使用空值退出控件,但它会恢复为原始值.删除日期格式似乎没有区别(它只是显示06/01/2011 00:00:00而不是所需的06/01/2010).根本没有其他代码引用该文本框.我认为在VS2003和VS2008之间的数据绑定控件的验证中必定会有一些改变,但是我很可能会遗漏一些令人头脑麻木的东西.
有任何想法吗?
TL;DR原因:
请参阅此Microsoft Connect建议:Provide better databinding support for nullable types
长版:
本质上发生的是当您清除文本框(到空字符串)并随后标签离开时,绑定将您的空字符串转换为DBNull值,然后传播到数据源但绑定,因为它是两个 – 然后,尝试以适当的格式重新填充绑定控件(文本框),并失败,导致文本框显示不允许从中删除焦点的奇怪行为!
这是由于DataSourceNullValue的DataSourceNullValue属性而发生的.这可以使用其中一个Binding类构造函数重载来设置,或者通过属性设置单独设置,但是,如果您没有显式设置此属性,请务必注意:
The default is DBNull for value types
and null for non-value types.
看来你没有明确地设置它,所以默认是应用,并且你的DateTime是value type,它正在使用DBNull.
一旦数据源更新(到DBNull),绑定机制将尝试使用新更新的数据源值重新填充文本框.当基础数据源值为DBNull时,用于绑定控件的值由Binding类的NullValue property控制.同样,如果未通过相关的重载构造函数参数或通过属性设置本身显式设置此属性,则默认值将适用,即:
The Object to be set as the control
property when the data source contains
a DBNull value. The default is null.
当然,Textbox’s Text property只能设置为类型为System.String的对象而不是空值(VB中为Nothing),因此TextBox无法将数据源值(DBNull)的代表值(null / nothing)绑定到约束控制.
纠正此行为的方法是确保将Binding class’s NullValue property显式设置为合适的值.在这种情况下,零长度字符串就足以纠正问题.
实现此目的的一种方法是更改线路:
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text",True))
至:
Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text",True,DataSourceUpdateMode.OnValidation,""))
这里的关键是最后一个参数,即NullValue,设置为零长度字符串(由于构造函数的参数,DataSourceUpdateMode也是显式指定的,但无论如何它都设置为默认值).
尽管如此,如果不是真正的错误,它似乎确实有些“奇怪”的行为.其他似乎遇到同样问题的人也证明了这一点(在Visual Studio 2010 / .NET 4.0中仍然很普遍!).在social.msdn.microsoft.com论坛上的This thread包含遇到相同问题的人,以及为什么会发生这种情况的一些有趣的可能解释,以及为什么Microsoft以这种方式设计它.
还有一个Microsoft Connect suggestion在2005年报道,突出了这个问题.这个建议已经“暂缓结束”.似乎微软并不认为这是一个错误,因为存在一个非常合理的解决方法(Binding的NullValue属性的显式设置),为了便于阅读,可以说,无论如何都应该这样做.他们显然会考虑将来的建议.
回到.NET 2.0(Visual Studio 2005)之前不存在的原因似乎是因为整个数据绑定机制已经完全针对.NET Framework 2.0的发布进行了修改.作为VS2003项目的原始解决方案是使用.NET Framework 1.1,它没有丰富的数据绑定功能集.虽然我不再需要VS2003的副本来测试这个,但我假设.NET 1.1中的绑定机制更多地使用了控件的值和数据源的值之间的隐式转换.当您检查.NET 1.1中的Binding类与.NET 2.0(或更高版本)相比时,这似乎得到支持.例如,没有办法(轻松)控制实际的双向绑定本身(以及如何在表单和数据源之间转换值)或所述值的格式.