取消数据绑定控件验证事件不会抑制尝试更新数据源

时间:2009-11-02 13:28:24

标签: .net vb.net winforms validation data-binding

我没有得到绑定到业务对象中的整数属性的TextBox所期望的行为。

这就是我的所作所为:

(1)将TextBox的DataSourceUpdateMode设置为:OnValidation

(2)在TextBox的Validating事件中,如果Integer.TryParse失败,请设置e.Cancel = True

(3)向Binding.ParseBinding.BindingComplete添加处理程序,并在处理程序中放置断点。

运行应用程序,将“asdasd”放在TextBox和tab中。 尽管设置了e.Cancel = True,但ParseBindingComplete事件都会被提升。 根据文档,设置e.Cancel = True应该禁止任何进一步的逻辑。

我搜索了MSDN以找出发生这种情况的原因,但我找不到任何东西。有没有人知道我在哪里可以得到一些细节?

ETA :我还为Validated事件添加了一个句柄。这是事件的顺序:

错误数据:

(1)验证。 (我设置e.Cancel = True

(2)Parse

(3)BindingComplete

好数据:

(1)验证

(2)Parse

(3)BindingComplete

(4)验证

ETA2 :更多信息和解决方法。

此行为的问题是,如果您有一些未在属性设置器中实现的验证。

例如,假设我的整数属性必须是奇数。我没有在属性设置器中检查这个,所以我在验证事件中进行检查。

正如您所看到的,从上面的行为来看,即使我取消验证,作为合法整数的值也会被写入数据源。

尽管数据源已更新,但如果您在验证事件中设置了“取消”,则不会触发Validated事件,因此您仍然可以阻止用户继续进行。

变通::

要停止数据源更新,您需要在Binding.Parse事件中进行验证,并抛出异常 - 这会阻止Binding成功完成。

2 个答案:

答案 0 :(得分:2)

添加对CancelEdit的调用似乎有所不同。

    private void textBox1_Validating(object sender, CancelEventArgs e)
    {
        bindingSource1.CancelEdit();
        e.Cancel = true;
    }

答案 1 :(得分:0)

我知道这已经过时了,但我花了太多时间寻找相同的答案。我希望这可以帮助其他人。 CodeMag有一篇关于对象绑定的非常好的文章可能有所帮助。

Object Binding Tips and Tricks by 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

修改

这是使用Visual Studio 2013和.Net4.6

创建的