无法转义空文本框

发布于 2024-10-10 08:02:56 字数 1432 浏览 0 评论 0 原文

我正在尝试找出最近从 VS2003 升级到 VS2008 的应用程序中出现烦人的界面错误的原因(该错误在迁移前不存在)。 发生的情况是这样的:

1) 用户单击包含日期的文本框。
2) 用户清除日期
3) 用户尝试移动到另一个字段,但不能。没有出现错误消息 - 就好像验证失败一样。

更多信息:

1)文本框的 Text 属性绑定到使用数据表作为其源的数据视图。绑定字段是一个可为 null 的日期时间字段,没有约束或默认值。
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", Me.dvClientNos, "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 之间的数据绑定控件验证肯定发生了一些变化,但我也很可能遗漏了一些明显的令人麻木的东西。

有什么想法吗?

I'm trying to track down the cause of an annoying interface bug in an app that was recently upgraded from VS2003 to VS2008 (the bug did not exist pre-migration).
What happens is this :

1) User clicks in textbox containing a date.
2) User clears date
3) User tries to move to another field, but can't. No error messages appear - it's as if the validation failed.

Further info :

1) The textbox's Text property is bound to a dataview which uses a datatable as its source. The bound field is a nullable datetime field with no constraints or default.
2) The Validating event fires and the CancelEventArgs property is not set to Cancel. The Validated, LostFocus and Leave events all fire as well, going LostFocus > Leave > Validating
3) I can't see any code changes relating to the control or the datasource with a couple of exceptions. The first is that this :

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd"))

has now changed to this :

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True))

The second is that this :

Me.dcolRangeEnd.DataType = GetType(System.DateTime)

has now changed to this :

Me.dcolRangeEnd.DataType = GetType(Date)

There is also this, which has been in the code since day one :

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

Now, if I remove the ", True" from the adding of the databinding then I can exit the control with a blank value, but it then reverts to the original value. Removing the date formatting appears to make no difference to this (it just reverts to showing 06/01/2011 00:00:00 rather than the desired 06/01/2010). No other code refers to that textbox at all. I'm thinking something must have changed in validation of databound controls between VS2003 and VS2008, but it's just as likely I'm missing something mind-numbingly obvious.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薄荷梦 2024-10-17 08:02:56

您看到观察到的行为的原因与 Windows 窗体及其数据绑定处理 NULL 数据库值的方式有关。

TL;DR 原因:

请参阅此 Microsoft Connect 建议:为可空类型提供更好的数据绑定支持

长版本:

本质上发生的是,当您清除文本框(为空字符串)并随后按 Tab 离开时,绑定会将您的空字符串转换为 DBNull 值,然后传播到数据源,但绑定,因为它是两个 -方式,然后尝试使用适当的格式重新填充绑定控件(文本框),但失败,导致文本框显示不允许从中移除焦点的奇怪行为!

发生这种情况是由于 DataSourceNullValue 绑定类的属性。这可以使用 Binding 类构造函数重载之一进行设置,或者通过属性设置单独设置,但是,如果您没有显式设置此属性,请务必注意:

值类型的默认值为 DBNull
对于非值类型则为 null。

看来您没有明确设置此项,因此应用默认值,并且您的 DateTime 为 值类型,它使用的是DBNull。

一旦数据源被更新(到 DBNull),绑定机制将尝试使用新更新的数据源值重新填充文本框。当基础数据源值为 DBNull 时,用于绑定控件的值由 Binding 类的 NullValue 属性。同样,如果未通过相关重载构造函数参数或属性设置本身显式设置此属性,则将应用默认值,即:

要设置为控件的对象
当数据源包含时的属性
DBNull 值。 默认值为空。

当然,一个文本框的 Text 属性 只能设置为 System.String 而不是空值(VB 中为 Nothing),因此 TextBox 无法将数据源值(DBNull)的代表值(null/nothing)绑定到绑定控件。

纠正此行为的方法是确保 绑定类的 NullValue 属性 已显式设置为合适的值。在这种情况下,零长度字符串足以解决该问题。

实现此目的的一种方法是将行:更改

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True))

为:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True, DataSourceUpdateMode.OnValidation, ""))

这里的关键是最后一个参数,即 NullValue,设置为零长度字符串(DataSourceUpdateMode 由于构造函数的参数也被显式指定,但无论如何它都被设置为默认值) 。

尽管如此,如果不是真正的错误,它确实看起来有些“奇怪”的行为。其他似乎遇到相同问题的人也证明了这一点(这在 Visual Studio 2010/.NET 4.0 中仍然普遍存在!)。 此主题 Social.msdn.microsoft.com 论坛上包含遇到相同问题的人,并提供了一些有趣的可能解释,说明为什么会发生这种情况,以及 Microsoft 为何这样设计。

还有一个 Microsoft Connect 建议 早在 2005 年就有报道强调了这个问题。该建议已“因推迟而关闭”。看来微软并不认为这是一个错误,因为存在一个非常合理的解决方法(绑定的 NullValue 属性的显式设置),可以说,为了可读性,无论如何都应该这样做。他们将来显然会考虑这个建议。

回到为什么在 .NET 2.0 (Visual Studio 2005) 之前不存在这种情况似乎是因为整个数据绑定机制针对 .NET Framework 2.0 的发布进行了彻底修改。您最初的解决方案是一个 VS2003 项目,它使用 .NET Framework 1.1,它没有那么丰富的数据绑定功能集。虽然我不再有 VS2003 的副本来测试这一点,但我假设 .NET 1.1 中的绑定机制更多地使用了控件值和数据源值之间的隐式转换。当您检查 .NET 1.1,与 .NET 2.0(或更高版本)。例如,无法(轻松)控制实际的双向绑定本身(以及如何在表单和数据源之间转换值)或所述值的格式。

The reason that you're seeing the observed behaviour is to do with how Windows Forms and it's Data Binding handles NULL database values.

The TL;DR reason:

See this Microsoft Connect suggestion: Provide better databinding support for nullable types

The long version:

What is essentially happening is that as you clear the Textbox (to an empty string) and subsequently tab away, the binding is converting your empty string to a DBNull value which is then propagated to the data source however the binding, since it is two-way, then attempts to re-populate the bound control (the Textbox) with appropriate formatting, and fails, causing the Textbox to display the strange behaviour of not allowing the focus to be removed from it!

This is happening due to the DataSourceNullValue property of the Binding class. This can be set using one of the Binding classes constructor overloads, or set separately via a property setting, however, if you do not explicitly set this property, it is important to note that:

The default is DBNull for value types
and null for non-value types.

It appears that you're not explicitly setting this, so the default is applying, and with your DateTime being a value type, it is using DBNull.

Once the data source has been updated (to DBNull), the binding mechanism will attempt to then repopulate the Textbox with the newly updated data source value. When the underlying data source value is DBNull, the value used for the bound control is governed by the Binding class's NullValue property. Again, if this property is not explicitly set either via the relevant overloaded constructor argument or via the property setting itself, the default value will apply, which is:

The Object to be set as the control
property when the data source contains
a DBNull value. The default is null.

Of course, a Textbox's Text property can only be set to an object of type System.String and not a null value (Nothing in VB), so the TextBox fails to bind the representative value (null/nothing) of the data source's value (DBNull) to the bound control.

The way to correct this behaviour is to ensure that the Binding class's NullValue property is explicitly set to a suitable value. In this case, a zero-length string will suffice to correct the problem.

One way to achieve this is to change the line:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True))

to:

Me.txtRangeEnd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.dvClientNos, "RangeEnd", True, DataSourceUpdateMode.OnValidation, ""))

The key here is the very last parameter, which is the NullValue, set to a zero-length string (The DataSourceUpdateMode is also explicitly specified due to the arguments of the constructor, but it's being set to it's default value anyway).

Despite all of this, it does appear to be somewhat "odd" behaviour, if not an actual bug. This is also evidenced by others who appear to be experiencing the same issue (which is still prevalent in Visual Studio 2010/.NET 4.0!). This thread on the social.msdn.microsoft.com forums contains someone experiencing the same issue with some interesting possible explanations as to why this happens, and why Microsoft designed it this way.

There is also a Microsoft Connect suggestion that was reported back in 2005 that highlights the issue. This suggestion has been "Closed as Postponed". It appears that Microsoft do not consider it a bug, as a very reasonable workaround exists (the explicit setting of the Binding's NullValue property) which, arguably, should be done anyway for readability's sake. They will apparently consider the suggestion in the future.

Going back to why this didn't exist pre-.NET 2.0 (Visual Studio 2005) seems to be due to the fact that the entire data binding mechanism was completely revamped for the release of .NET Framework 2.0. Your original solution, being a VS2003 project was using .NET Framework 1.1 which did not have as rich a data binding feature-set. Although I no longer have a copy of VS2003 to hand to test this, I'm assuming the binding mechanism in .NET 1.1 made much more use of implicit conversions between the control's value and the data source's value. This appears to be supported when you examine the Binding class from .NET 1.1, compared with .NET 2.0 (or higher). For example, there was no way to (easily) control the actual two-way binding itself (and how values are converted between the form and the data source) or the formatting of said values.

美男兮 2024-10-17 08:02:56

我以前遇到过这种类型的错误,我必须确保基础数据源(在我的例子中它是一个数据集)没有设置为只读并且该列允许“空”值。

一旦我完成了这一切,一切就都正常了。数据绑定中抛出的错误似乎被某处吞噬并且没有传播。

I have had this type of error before and I had to ensure that the underlying data source (in my case it was a dataset) was not set to read only and that the column allowed `null' values.

Once I had done this everything worked fine. It seemed like that the error that was being thrown in the Data Bindings was swallowed up somewhere and didn't propagate up.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文