Не удается выбрать пустое текстовое поле - PullRequest
9 голосов
/ 06 января 2011

Я пытаюсь отследить причину раздражающей ошибки интерфейса в приложении, которое было недавно обновлено с VS2003 до VS2008 (до миграции не существовало). Что происходит, это:

1) Пользователь нажимает на текстовое поле с датой.
2) Пользователь очищает дату
3) Пользователь пытается перейти в другое поле, но не может. Сообщения об ошибках не отображаются - как будто проверка не удалась.

Дополнительная информация:

1) Свойство Text текстового поля привязано к просмотру данных, который использует данные в качестве своего источника. Связанное поле является пустым полем даты и времени без ограничений или значений по умолчанию.
2) Событие Validating возникает, и свойство CancelEventArgs не имеет значения Cancel. Все события Validated, LostFocus и Leave также запускаются: LostFocus> Leave> Validating
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, но вполне вероятно, что я упускаю что-то невероятно очевидное.

Есть идеи?

Ответы [ 2 ]

9 голосов
/ 07 февраля 2011

Причина, по которой вы наблюдаете наблюдаемое поведение, связана с тем, как Windows Forms и ее привязка данных обрабатывают значения базы данных NULL.

TL; DR причина:

См. Это предложение Microsoft Connect: Обеспечение лучшей поддержки привязки данных для обнуляемых типов

Длинная версия:

По сути, происходит то, что когда вы очищаете текстовое поле (в пустую строку) и впоследствии вкладываетесь в него, привязка преобразует вашу пустую строку в значение DBNull , которое затем распространяется в источник данных. однако привязка, поскольку она двусторонняя, затем пытается повторно заполнить связанный элемент управления (текстовое поле) с соответствующим форматированием и завершается неудачно, в результате чего текстовое поле отображает странное поведение, не позволяющее удалить фокус с него!

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

По умолчанию DBNull для типов значений и нуль для типов без значения.

Похоже, что вы не устанавливаете это явно, поэтому применяется значение по умолчанию, а ваш DateTime имеет тип значения , он использует DBNull.

После обновления источника данных (до DBNull) механизм привязки попытается затем снова заполнить текстовое поле новым значением источника данных. Когда базовым значением источника данных является DBNull, значение, используемое для привязанного элемента управления, определяется свойством NullValue класса Binding . Опять же, если это свойство не установлено явно ни через соответствующий перегруженный аргумент конструктора, ни через сам параметр свойства, будет применяться значение по умолчанию, а именно:

Объект, который будет установлен как элемент управления свойство, когда источник данных содержит значение DBNull. По умолчанию установлено значение null.

Конечно, Свойство Text для Textbox может быть установлено только для объекта типа System.String , но не для нулевого значения (ничего в VB), поэтому TextBox не может привязать репрезентативное значение (ноль / ничего) значения источника данных (DBNull) к связанному элементу управления.

Способ исправить это поведение состоит в том, чтобы убедиться, что свойство NullValue класса Binding явно установлено в подходящее значение. В этом случае для устранения проблемы будет достаточно строки нулевой длины.

Один из способов добиться этого - изменить строку:

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 году, которое освещает эту проблему. Это предложение было "Закрыто как отложено". Похоже, что Microsoft не считает это ошибкой, поскольку существует очень разумный обходной путь (явная установка свойства NullValue в Binding), который, возможно, следует сделать в любом случае для удобства чтения. По-видимому, они рассмотрят это предложение в будущем.

Возвращаясь к тому, почему этого не было до .NET 2.0 (Visual Studio 2005), кажется, связано с тем, что весь механизм привязки данных был полностью переработан для выпуска .NET Framework 2.0. Ваше первоначальное решение, будучи проектом VS2003, использовало .NET Framework 1.1, у которого не было такого богатого набора функций привязки данных. Хотя для проверки этого у меня больше нет копии VS2003, я предполагаю, что механизм привязки в .NET 1.1 гораздо шире использовал неявные преобразования между значением элемента управления и значением источника данных. Это кажется поддерживаемым, когда вы изучаете класс Binding из .NET 1.1 , по сравнению с .NET 2.0 (или выше). Например, не было никакого способа (легко) управлять самим фактическим двусторонним связыванием (и тем, как значения преобразуются между формой и источником данных) или форматированием указанных значений.

0 голосов
/ 07 февраля 2011

У меня раньше был такой тип ошибки, и я должен был убедиться, что базовый источник данных (в моем случае это был набор данных) не был настроен только на чтение и чтобы столбец допускал значения 'null'.

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

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