Сбой Decimal.TryParse для TextBox.Leave и TextBox.LostFocus - PullRequest
1 голос
/ 22 декабря 2010

Это, должно быть, одна из самых разочаровывающих глупых ошибок, с которыми я когда-либо сталкивался, и я просто хочу посмотреть, сталкивался ли кто-нибудь еще с этим раньше.

Вот сделка.У меня есть TextBox в приложении Windows Forms в VB 2008 (.NET 3.5), где пользователь может ввести оценочную сумму.Я позволяю им набирать доллары и центы и хочу округлить до ближайшего доллара.Исходный код имел округление вниз, когда данные были записаны обратно в таблицу, и это работало нормально - у меня есть этот код в подпрограмме «Сохранить», которая запускается, когда пользователь переходит на другой экран или запись:

    Dim est As Decimal : Decimal.TryParse(txtEstimateAmount.Text.Trim, est)
    Dim estimatedAmount As Integer = Math.Round(est)

Я решил, что было бы неплохо на самом деле выполнить округление, как только они вместо этого покидают поле, поэтому они не удивляются, когда перезагружают экран и обнаруживают, что 1822.60 теперь 1823. Поэтому я взял точно такой жекод и добавил его в обработчик событий TextBox.Leave.И случилось самое странное: вместо переменной est , заполненной 1822.60 после разбора, она устанавливается в -1!Что за...?

Отладка обработчика показывает, что значение правильно попадает в синтаксический анализатор, и если я выполняю синтаксический анализ вручную через окно Immediate, он анализируется правильно, но когда я позволяю коду сделать это, он неизменно получает значение1.Еще более странным является то, что любое число анализируется как -1, а не только как десятичные дроби, а любое не числовое значение анализируется как 0 (это правильно).

Кто-нибудь еще сталкивалсяэто раньше?Я попытался переместить код в событие TextBox.LostFocus, но с теми же результатами.Я понятия не имею, что, черт возьми, происходит, и, очевидно, есть множество обходных путей для этого, но это просто не имеет никакого смысла.

РЕДАКТИРОВАТЬ: Вот полный обработчик событий (текущее поведение, для которого нужно положить -1 в TextBox):

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

Ответы [ 2 ]

5 голосов
/ 22 декабря 2010

Во-первых, вам действительно нужно сделать это с помощью обработчика события 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

Объяснить -1 сложно.TryParse обычно пишет 0, если не может разобрать текст.Следите за изменением свойства CurrentCulture потока пользовательского интерфейса.И любые изменения, внесенные в настройки формата в Панели управления + Регион и языковой апплет.

2 голосов
/ 22 декабря 2010

Я не думаю, что код, который вы разместили, - это код, который вы запускаете. Что происходит, это:

Dim est As Decimal = Decimal.TryParse(txtEstimateAmount.Text.Trim, est)     
Dim estimatedAmount As Integer = Math.Round(est) 

Я бы сделал чистку и перестроил или попытался бы переписать его в другом формате, возможно, с логическим значением, чтобы получить результат попытки трипсинга.

РЕДАКТИРОВАТЬ теперь, когда я видел ваш реальный код. Вы действительно помещаете истину / ложь из трипарсного результата в самое десятичное. Удалить est =. Est загружается, потому что он передается по ссылке в tryparse.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...