none
Problème de DataError lors d'un déplacement dans une BindingSource RRS feed

  • Question

  • Bonjour à tous,

    Je rencontre un petit problème de gestion d'erreur dans une DataTable lorsque celle-ci est liée à une BindingSource et que l'évènement MoveNext de la source est provoqué alors qu'il existe des erreurs de saisie dans mes champs du formulaire.

    Voici, ci-dessous, un petit exemple qui illustre ce problème. A l'initialisation d'un formulaire, je crée une table "Names" qui contient une colonne "Name" de type chaîne qui ne peut pas être vide, doit être unique et ne peut pas dépasser 4 caractères.

    Je crée une BindingSource liée à ma table, un BindingNavigator lié à ma source et un TextBox lié à la colonne "Name" de ma source.

    Au chargement du formulaire je simule un "Name" trop long dans le champ texte et tente de passer à l'enregistrement suivant.

    On peut constater qu'une exception est générée lors du déplacement, mais qu'à aucun moment la source n'a générée d'évènement DataError ou de BindingComplete avec erreur.

    Voici le code :

    Public Class Form1 Private WithEvents myTextBox As TextBox Private WithEvents myNavigator As BindingNavigator Private WithEvents myNavigatorMovePreviousItem As ToolStripButton Private WithEvents myNavigatorMoveNextItem As ToolStripButton Private WithEvents myDataTable As DataTable Private WithEvents mySource As BindingSource Public Sub New() ' Cet appel est requis par le Concepteur Windows Form. InitializeComponent() ' Ajoutez une initialisation quelconque après l'appel InitializeComponent(). InternalInitializeComponent() End Sub 'Form1 load Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 'Simule un MaxLength ArgumentException myTextBox.Text = "IamToLong" myNavigator.MoveNextItem.PerformClick() ' mySource.MoveNext() 'Ou si le formulaire contient une ListBox liée à la source et que l'utilisateur provoque

    'un SeletedIndexChanged et dans ce cas, on ne peut pas annuler cet évènement 'Comme vous pouvez le constater, le résultat de la console est : ' ' myTextBox_BindingComplete | BindingCompleteState=Success ; ErrorText= ; ExceptionHandled=False ; ExceptionMessage= ' mySource_BindingComplete | BindingCompleteState=Success ; ErrorText= ; ExceptionHandled=False ; ExceptionMessage= ' 'BindingCompleteState toujours en "Success" et aucun mySource_DataError lancé End Sub Private Sub InternalInitializeComponent() myTextBox = New TextBox() myNavigator = New BindingNavigator() myNavigatorMovePreviousItem = New ToolStripButton() myNavigatorMoveNextItem = New ToolStripButton() myDataTable = CreateDataTable() mySource = New BindingSource() 'mySource mySource.DataSource = myDataTable 'myTextBox Dim bind As Binding = myTextBox.DataBindings.Add("Text", mySource, "Name", True, DataSourceUpdateMode.OnValidation, DBNull.Value) AddHandler bind.BindingComplete, AddressOf myTextBox_BindingComplete myTextBox.Location = New System.Drawing.Point(12, 40) myTextBox.Name = "myTextBox" myTextBox.Size = New System.Drawing.Size(141, 20) myTextBox.TabIndex = 1 'myNavigator myNavigator.Items.AddRange(New ToolStripItem() {myNavigatorMovePreviousItem, myNavigatorMoveNextItem}) myNavigator.Location = New System.Drawing.Point(0, 0) myNavigator.MoveNextItem = myNavigatorMoveNextItem myNavigator.MovePreviousItem = myNavigatorMovePreviousItem myNavigator.BindingSource = mySource myNavigator.Name = "myNavigator" myNavigator.Size = New System.Drawing.Size(367, 25) myNavigator.TabIndex = 0 'myNavigatorMovePreviousItem myNavigatorMovePreviousItem.DisplayStyle = ToolStripItemDisplayStyle.Text myNavigatorMovePreviousItem.Name = "myNavigatorMovePreviousItem" myNavigatorMovePreviousItem.RightToLeftAutoMirrorImage = True myNavigatorMovePreviousItem.Size = New System.Drawing.Size(50, 22) myNavigatorMovePreviousItem.Text = "Previous" 'myNavigatorMoveNextItem myNavigatorMoveNextItem.DisplayStyle = ToolStripItemDisplayStyle.Text myNavigatorMoveNextItem.Name = "myNavigatorMoveNextItem" myNavigatorMoveNextItem.RightToLeftAutoMirrorImage = True myNavigatorMoveNextItem.Size = New System.Drawing.Size(50, 22) myNavigatorMoveNextItem.Text = "Next" 'Form1 Me.Controls.Add(myNavigator) Me.Controls.Add(myTextBox) End Sub Private Function CreateDataTable() As DataTable Dim result As New DataTable() Dim nameColumn As New DataColumn() 'Column name nameColumn.AllowDBNull = False nameColumn.Caption = "Name" nameColumn.ColumnName = "Name" nameColumn.DataType = GetType(String) nameColumn.DefaultValue = DBNull.Value nameColumn.MaxLength = 4 nameColumn.ReadOnly = False nameColumn.Unique = True 'Table result.TableName = "Names" result.Columns.Add(nameColumn) result.Rows.Add(New Object() {"Bill"}) result.Rows.Add(New Object() {"Bob"}) Return result End Function 'myTextBox binding complete event Private Sub myTextBox_BindingComplete(ByVal sender As Object, ByVal e As BindingCompleteEventArgs) If e.BindingCompleteContext = BindingCompleteContext.DataSourceUpdate Then Dim exceptionMessage As String = String.Empty If e.Exception IsNot Nothing Then exceptionMessage = e.Exception.Message Console.WriteLine("myTextBox_BindingComplete | BindingCompleteState={0} ; ErrorText={1} ; ExceptionHandled={2} ; ExceptionMessage={3}", _ e.BindingCompleteState.ToString(), _ e.ErrorText, _ e.Exception IsNot Nothing, _ exceptionMessage) End If End Sub 'mySource binding complete event Private Sub mySource_BindingComplete(ByVal sender As Object, ByVal e As BindingCompleteEventArgs) Handles mySource.BindingComplete If e.BindingCompleteContext = BindingCompleteContext.DataSourceUpdate Then Dim exceptionMessage As String = String.Empty If e.Exception IsNot Nothing Then exceptionMessage = e.Exception.Message Console.WriteLine("mySource_BindingComplete | BindingCompleteState={0} ; ErrorText={1} ; ExceptionHandled={2} ; ExceptionMessage={3}", _ e.BindingCompleteState.ToString(), _ e.ErrorText, _ e.Exception IsNot Nothing, _ exceptionMessage) End If End Sub 'mySource data error event Private Sub mySource_DataError(ByVal sender As Object, ByVal e As BindingManagerDataErrorEventArgs) Handles mySource.DataError Console.WriteLine("mySource_DataError | ExceptionMessage={0}", e.Exception.Message) End Sub End Class

    Je sais que l'on pourrait faire un TryCatch autour du MoveNext, mais comme je l'ai précisé en commentaire dans le code, si l'évènement est provoqué par une ListBox, on ne le maîtrise pas et on ne peut pas l'annuler en cas d'erreur.

    Comment faire pour traiter proprement ce cas selon vous ?

    Merci d'avance.

    dimanche 10 juin 2012 09:23

Toutes les réponses

  • Bonjour,

    Peut être vous faut-il limiter la longueur de la chaine du textbox

    'Simule un MaxLength ArgumentException
            myTextBox.Text = "IamToLong"
            myTextBox.Text = Microsoft.VisualBasic.Left(myTextBox.Text, 4)
            myNavigator.MoveNextItem.PerformClick()

    Cordialement,

    Boris R.

    lundi 26 août 2013 13:59