Отмена события проверки элемента управления с привязкой к данным не подавляет попытку обновления источника данных - PullRequest
8 голосов
/ 02 ноября 2009

Я не получаю ожидаемого поведения для TextBox, привязанного к целочисленному свойству в бизнес-объекте.

Вот что я сделал:

(1) Установите DataSourceUpdateMode, для TextBox: OnValidation.

(2) В событии Validating для TextBox установите e.Cancel = True, если Integer.TryParse завершится неудачей.

(3) Добавьте обработчик к Binding.Parse и Binding.BindingComplete и установите точки останова в обработчиках.

Запустите приложение, поместите «asdasd» в TextBox и откройте вкладку. Несмотря на установку e.Cancel = True, оба события Parse и BindingComplete возникают. Согласно документации, настройка e.Cancel = True должна подавлять дальнейшую логику.

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

ETA : Я также добавил дескриптор события Validated. Вот последовательность событий:

Неверные данные:

(1) Проверка. (Я установил e.Cancel = True)

(2) Parse

(3) BindingComplete

Хорошие данные:

(1) Проверка

(2) Parse

(3) BindingComplete

(4) Утверждено

ETA2 : немного больше информации и обходной путь.

Проблема с этим поведением заключается в том, что у вас есть некоторая проверка, которая не реализована в установщике свойств.

Например, допустим, мое целочисленное свойство должно быть нечетным числом. Я не проверяю это в установщике свойств, поэтому я проверяю событие проверки.

Как видно из приведенного выше поведения, значение в виде допустимого целого числа будет записано в источник данных, даже если я отменю проверку.

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

обходным ::

Чтобы остановить обновление источника данных, необходимо выполнить проверку в событии Binding.Parse и выдать исключение, которое препятствует успешному завершению привязки.

Ответы [ 2 ]

2 голосов
/ 24 октября 2012

Добавление вызова к CancelEdit, кажется, имеет значение.

    private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        bindingSource1.CancelEdit();
        e.Cancel = true;
    }
0 голосов
/ 09 мая 2018

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

Советы и рекомендации по привязке объектов от CodeMag

Это форма, которую я создал для проверки написанного мной кода.

Test Form with no Errors

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

Test Form with Errors

Ключом к возможности отмены обновления является включение e.Binding.BindingManagerBase.CancelCurrentEdit() в событие завершения bindingsource.

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Class frmTest

Private WithEvents PersonBindingSource As New Person
Private WithEvents ErrorProvider1 As New ErrorProvider
Private WithEvents FirstNameBinding As Binding
Private WithEvents AgeBinding As Binding

Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Me.ErrorProvider1.ContainerControl = Me
End Sub

Private Sub frmTest_Load(sender As Object, e As EventArgs) Handles Me.Load
    ErrorProvider1.DataSource = PersonBindingSource

    FirstNameBinding = TextBox1.DataBindings.Add("Text", PersonBindingSource, "FirstName", True, DataSourceUpdateMode.OnValidation)
    AgeBinding = TextBox2.DataBindings.Add("Text", PersonBindingSource, "Age", True, DataSourceUpdateMode.OnValidation)

End Sub

Private Sub FirstNameBinding_BindingComplete(sender As Object, e As BindingCompleteEventArgs) Handles FirstNameBinding.BindingComplete
    If Not e.BindingCompleteState = BindingCompleteState.Success Then
        e.Binding.BindingManagerBase.CancelCurrentEdit()
    End If
End Sub

Private Sub AgeBinding_BindingComplete(sender As Object, e As BindingCompleteEventArgs) Handles AgeBinding.BindingComplete
    If Not e.BindingCompleteState = BindingCompleteState.Success Then
        e.Binding.BindingManagerBase.CancelCurrentEdit()
    End If
End Sub

End Class

Публичный класс для человека

Public Class Person
Implements INotifyPropertyChanged

Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

Protected Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyname As String = Nothing)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyname))
End Sub

Private _FirstName As String = "First Name"
Public Property FirstName() As String
    Get
        Return _FirstName
    End Get
    Set(ByVal value As String)
        If value.Length > 10 Then
            Throw New Exception("First name must be shorter than 10 characters")
        End If
        If (value <> _FirstName) Then
            _FirstName = value
            NotifyPropertyChanged()
        End If
    End Set
End Property

Private _Age As Decimal = 21
Public Property Age() As Decimal
    Get
        Return _Age
    End Get
    Set(ByVal value As Decimal)
        If value > 50 Then
            Throw New Exception("A person cannot be older than 50")
        ElseIf value < 21 Then
            Throw New Exception("A person cannot be younger than 21")
        ElseIf (value <> _Age) Then
            _Age = value
            NotifyPropertyChanged()
        End If
    End Set
End Property

End Class

EDIT:

Это было создано с использованием Visual Studio 2013 с .Net4.6

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