Decimal.TryParse在TextBox.Leave和TextBox.LostFocus上失败

Mik*_*oux 1 vb.net textbox decimal .net-3.5 winforms

这一直是我遇到的最令人沮丧的愚蠢错误之一,我只是想看看其他人是否曾遇到此问题.

这是交易.我在VB 2008(.NET 3.5)中的Windows窗体应用程序中有一个TextBox,用户可以在其中键入估计数量.我允许他们兑换美元和美分,我想要四舍五入到最接近的美元.原始代码在将数据写回表时进行了舍入,并且工作正常 - 我将此代码放在"保存"例程中,当用户移动到不同的屏幕或记录时触发该例程:

    Dim est As Decimal : Decimal.TryParse(txtEstimateAmount.Text.Trim, est)
    Dim estimatedAmount As Integer = Math.Round(est)
Run Code Online (Sandbox Code Playgroud)

我决定,一旦他们离开现场实际进行舍入可能会很好,所以当他们重新加载屏幕并发现1822.60现在是1823时他们并不感到惊讶.所以我采用完全相同的代码并添加它到TextBox.Leave事件处理程序.并且发生了最奇怪的事情:在解析之后,不是使用1822.60填充变量est,而是将其设置为-1!什么......?

调试处理程序会显示该值正确进入解析器,如果我通过Immediate窗口手动解析,它会正确解析,但是当我让代码执行时,它总是设置为-1.甚至更奇怪的是,任何数字都被解析为-1,而不仅仅是小数,任何非数字都被解析为0(这是正确的).

有没有其他人遇到过这个?我尝试将代码移动到TextBox.LostFocus事件,但结果相同.我不知道到底发生了什么,显然有很多变通方法,但它没有任何意义.

编辑:这是完整的事件处理程序(当前行为是在TextBox中放置-1):

Private Sub txtEstimateAmount_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtEstimateAmount.Leave
    ' Take any dollars-and-cents amount and round to the nearest dollar
    Dim est As Decimal
    est = Decimal.TryParse(txtEstimateAmount.Text.Trim, est)
    txtEstimateAmount.Text = If(est <> 0, Math.Round(est).ToString(), String.Empty)
End Sub
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

首先,您确实需要使用Validating事件处理程序执行此操作,以便您可以捕获垃圾并避免忽略TryParse的返回值.像这样:

Private Sub TextBox1_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
    Dim est As Decimal
    If TextBox1.Text.Length = 0 then Exit Sub   '' optional
    If Not Decimal.TryParse(TextBox1.Text.Trim, est) Then
        e.Cancel = True
        TextBox1.SelectAll()
    Else
        TextBox1.Text = est.ToString("N0")
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

解释-1很困难.如果TryParse无法解析文本,则通常会写入0.注意更改UI线程的CurrentCulture属性.以及对"控制面板+区域和语言"小程序中的格式设置所做的任何更改.