IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Annuler les modifications invalides depuis le dataGridView


Sujet :

VB.NET

  1. #1
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut Annuler les modifications invalides depuis le dataGridView
    Bonsoir a tous,
    Je suis en train de revisiter mes procédures de validations en particulier pour abandonner l'evevenement DataTable.ColumnChanging et utiliser les événements de validations plus standard coté contrôles UI.
    Tout mes contrôles (DataGridView + Contrôles standard sont DataBindés a un Bindingsource unique).
    je ne sais pas ou je me trompe mais je n'arrive pas a annuler annuler les modifications faite dans le DataGridView. Noter que la source de données n'est jamais mis a jour automatiquement a partir des contrôles simples (DataSourceUpdateMode.Never), les écritures dans mes tables sont ne sont réalisé seulement si les modifications sont valides (dans les événements Validated).

    Quelques lignes de code de paramétrages :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ' Paramétrage et liaisons a la source de données pou le DataGridView :
    DataGridView1.CausesValidation = True
    DataGridView1.DataSource = MainBindingSource
     
    ' liaison a la source de données pour les contrôles simples :
    Dim Bind as New Binding("Text", MainBindingSource, TableTaches.SUJET, True, DataSourceUpdateMode.Never)
    TextBoxSUJET.DataBindings.Add(Bind)
     
    ' je préfere déclencher moi même les événements de validation :
    Me.AutoValidate = Windows.Forms.AutoValidate.Disable
     
    ' Ces événements vont exécuter me.Validate :
    AddHandler DataGridView1.CurrentCellDirtyStateChanged, AddressOf EventFromUserControls
    AddHandler TextBoxSUJET.KeyDown, AddressOf EventFromUserControls
     
    ' Ces événements sont exécutés après me.validate
    AddHandler DataGridView1.Validating, AddressOf EventControlsValidating
    AddHandler TextBoxSUJET.Validating, AddressOf EventControlsValidating
    Les procédures principales :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    ' La procédure pour déclencher la validation du formulaire :
     Private Sub EventFromUserControls(ByVal sender As Object, ByVal e As System.EventArgs)
            Me.Validate()
        End Sub
     
    ' Procédure générique qui acceptent les événements de validation du DatagridView ainsi que les contrôles simples :
     Private Sub EventControlsValidating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
            Dim Ctrl As Control = CType(sender, Control)
            Dim ColChangingName As String = Nothing 
     
            If TypeOf Ctrl Is DataGridView Then
                ' la propriété dataBinding du Controle n'est pas assignée (Cas des DataGridView)
                Dim dg As DataGridView = CType(Ctrl, DataGridView)
                ColChangingName = dg.CurrentCell.OwningColumn.DataPropertyName
            Else
                ' la propriété dataBinding du Controle est assignée (Cas des Controles simples)
                ColChangingName = Ctrl.DataBindings.Item(0).BindingMemberInfo.BindingMember
            End If
     
            Dim ColChangingValue As Object = Nothing
            Dim RowView As DataRowView = CType(MainBindingSourceTaches.Current, DataRowView)
            Dim Row As DataRow = RowView.Row
            Dim OriginaleValue As Object = Row(ColChangingName)
            Dim Isvalide As Boolean = False
            Dim errorMsg As String = Nothing
     
            ' Obtient la valeur réelle du contrôle débarrassée de son formatage :
            Get_Ctrl_RealBindingValueWithoutFormat(sender, ColChangingValue)
     
            ' Retourne le résultat de la validation :
            Isvalide = CalculRowValues(Row, "UserControls", ColChangingName, ColChangingValue, errorMsg)
     
            If Isvalide = True Then
            ' Si c'est valide on  ne fait rien, les écritures sont effectués dans Validated
            Else
            ' Si c'es invalide on annule :
                If TypeOf Ctrl Is DataGridView Then
                    ' la propriété dataBinding du Controle n'est pas assignée (Cas des DataGridView)
                    Dim dg As DataGridView = CType(Ctrl, DataGridView)
                    e.Cancel = True
                Else
                    ' la propriété dataBinding du Controle est assignée (Cas des Controles simples)
                    e.Cancel = True
                    Ctrl.DataBindings.Item(0).ReadValue()
                End If
            End If
        End Sub
     
    ' Procédure générique, écrit dans la source de données si les modifications n'ont pas été annulées :
     
      Private Sub EventControlsValidated(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
            Dim Ctrl As Control = CType(sender, Control)
            Dim ColChangingName As String = Nothing
     
            If TypeOf Ctrl Is DataGridView Then
                ' la propriété dataBinding du Controle n'est pas assignée (Cas des DataGridView)
                Dim dg As DataGridView = CType(Ctrl, DataGridView)
                ColChangingName = dg.CurrentCell.OwningColumn.DataPropertyName
            Else
                ' la propriété dataBinding du Controle est assignée (Cas des Controles simples)
                ColChangingName = Ctrl.DataBindings.Item(0).BindingMemberInfo.BindingMember
            End If
     
            Dim ColChangingValue As Object = Nothing
            Dim RowView As DataRowView = CType(MainBindingSourceTaches.Current, DataRowView)
            Dim Row As DataRow = RowView.Row
            Dim OriginaleValue As Object = Row(ColChangingName)
            Dim Isvalide As Boolean = False
            Dim errorMsg As String = Nothing
     
            ' Obtient la valeur réelle du contrôle débarrassée de son formatage :
            Get_Ctrl_RealBindingValueWithoutFormat(sender, ColChangingValue)
     
            ' Ecrit dans le DataTable :
            Call WriteRowValues(Row, "UserControls", ColChangingName, ColChangingValue, errorMsg)
     
        End Sub
    Au passage vous noterait que j'utilise Ctrl.DataBindings.Item(0).ReadValue() pour "faire plus propre", je remets la valeur d'origine dans le contrôle si la modification est invalide. j'aimerais aussi faire de même dans le DataGridView mais le problème essentiel est l'annulation est surtout empêcher l'écriture dans la source.

    je suis ouvert pour toutes suggestions, il y a surement des choses que je ne fait pas correctement. Je sais aussi que je doit améliorer mon code (je trouve qu'il y trop de codes dupliqués entre validating et Validated).

    Merci a vous.

  2. #2
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour, j'ai avancé un peu mais j'ai toujours quelques problèmes

    En fait il faudrait que je règle le problème suivant avant de m'attaquer au reste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.AutoValidate = Windows.Forms.AutoValidate.Disable
    Cette ligne fonctionne bien dans le sens qu'elle désactive la validation automatique de tous les contrôles simples et me permet ainsi de définir moi-même les événements qui déclenche la validation avec me.Validate dans un TextBox.KeyDown.par exemple.
    Cependant cela n'a aucun effet sur le DataGridView, il faudrait que je désactive aussi la validation automatique du DatagridView, cela est surtout utilile losque je lance une procédure automatique qui réactualise certaines valeurs du dataGridView, faut t'il que je me désabonne aux événements du dataGridView avant de lancer cette procédure et me réabonner après ?

    L'idée c'est que je souhaite que la validation se déclenche uniquement lors d'une action utilisateur et non durant un traitement automatique. Cela fonctionne très bien avec les contrôles simples mais pas avec le DataGridView. Et je souhaite faire une procédure de validation unique quelque soit le contrôle qui déclenche la validation.

    Quelqu'un a une idée ?

  3. #3
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Je me suis un peu embrouillé dans mes explications .
    Tout d'abord j'ai oublié de préciser que mon dernier essai s'effectué avec l'événement DataGridView1.CellValidating et dans ce cas la validation du DataGridView se produit non pas pendant mon traitement automatique mais juste après Form.show. Et cela se termine par un message d'erreur :
    Échec de l'opération, car le programme n'a pas pu valider ou abandonner une modification de la valeur de cellule.
    (Je pense que c'est du au fait que mes conditions de validations ne sont jamais vrai mais c'est une logique normal puisque ça fait partie de mes rêgles métier : pour pouvoir modifier une ligne il faut être l'auteur de cette ligne ce qui n'est pas toujours le cas mais ça ne doit pas empêcher l'affichage du DataGridView et de ces lignes.) Et dans ces conditions je n'ai même pas pu vérifier que l'annulation avec e.cancel fonctionne bien.

    Deuxièmement :
    Si j'utilise l’événement DataGridView1.Validating comme dans mon code initial, cette fois l'événement de validation ne se déclenche plus après Form.show donc c'est un bon point de ce coté la mais je revient à mon problème du début, c'est a dire que je ne peux pas annuler les modifications.

  4. #4
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bon, j'ai avancé un tout petit peu.
    Déjà je n'ai plus le message d'erreur quand j'utilise l’événement DataGridView1.CellValidating, pour cela j'ai déplacé la ligne suivante dans Form.Load (cell-ci était dans le New)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DataGridView1.DataSource = MainBindingSource
    .
    Ensuite je m'appercois que CellValidating s’exécute chaque fois qu'une cellule perds le focus, cela vaux également pour les cellules qui sont remplis automatiquement comme les colonnes Id.
    Et dans mon ancienne procédure de validation je doit prendre en compte plusieurs choses :
    1- Je partais du principe qu'en entrant dans ma procédure rien n'est valide tant que je n'ai pas obtenu les conditions de validation.
    2 - Dans mes conditions de validations je ne gère pas les champs remplis automatiquement (Colonne Id).
    Dans ces conditions je ne peux pas sortir d'un état invalide pour me retrouver dans un état valide.
    Il faut donc que je fasse l'inverse, considérer que tout est valide sauf si je j'obtiens des conditions d’invalidités.
    Ceci fait j'y verrais peut-être plus clair mais je ne suis pas sûre que Cellvalidating répondent au fait que je veuille déclencher la validation uniquement sur une modification utilisateur.
    Je tourne rond..., c'est plus compliqué que je le pensais.
    Si je pouvais avoir des conseils ça m'aiderait beaucoup.

  5. #5
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Gérer de manière bien spécifique les modifications directement dans le DataGridView, c'est souvent mission impossible.

    Je conseille vraiment d'implémenter des boutons "ajouter", "supprimer" et "modifier" qui lance des formes d'édition avec des boutons de validation <OK> et <Cancel>.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  6. #6
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour Graffito, merci de me venir en aide.
    En fait j'ai aussi un formulaire d'édition. Pour celui-ci je pense utiliser la même procédure de validation que pour mon DataGridView et mes contrôlés simples puisque cette procédure accepte en entrée n'importe quel contrôle DataBindé.

    Sinon j'ai enfin trouvé quelque chose qui fonctionne en vérifiant que la cellule en cours de validation est en mode édition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If Cell.IsInEditMode Then
    Ce qui confirme que la validation est bien déclenchée par une modification utilisateur.

    Voici mon nouveau code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    Private Sub EventControlsValidating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
            Dim Ctrl As Control = CType(sender, Control)
            Dim ColChangingName As String = Nothing
            Dim ColChangingValue As Object = Nothing
            Dim RowView As DataRowView = CType(MainBindingSourceTaches.Current, DataRowView)
            Dim Row As DataRow = RowView.Row
            Dim OriginaleValue As Object = Nothing
            Dim Isvalide As Boolean = False
            Dim errorMsg As String = Nothing
     
            If TypeOf Ctrl Is DataGridView Then
                ' Controle DataGridView
                Dim dg As DataGridView = CType(Ctrl, DataGridView)
                Dim Cell As DataGridViewCell = dg.CurrentCell
                If Cell.IsInEditMode Then
                    ColChangingName = dg.CurrentCell.OwningColumn.DataPropertyName
     
                    Try
                        OriginaleValue = Row(ColChangingName)
                    Catch ex As Exception
                        ' ColChangingName ne fait pas partie du dataTable
                        Exit Sub
                    End Try
                    Get_Ctrl_RealBindingValueWithoutFormat(sender, ColChangingValue)
     
     
                    Isvalide = CalculRowValues(Row, "UserControls", ColChangingName, ColChangingValue, errorMsg)
     
                    If Isvalide = True Then
                    Else
                        Dim c As Control = dg.EditingControl
                        'dg.CancelEdit()
                        e.Cancel = True
                        dg.EndEdit()
                        Cell.Value = OriginaleValue
                    End If
                End If
     
            Else
                ' Controles simples
                ColChangingName = Ctrl.DataBindings.Item(0).BindingMemberInfo.BindingMember
     
                OriginaleValue = Row(ColChangingName)
     
                Get_Ctrl_RealBindingValueWithoutFormat(sender, ColChangingValue)
     
     
                Isvalide = CalculRowValues(Row, "UserControls", ColChangingName, ColChangingValue, errorMsg)
     
                If Isvalide = True Then
                Else
                    e.Cancel = True
                    Ctrl.DataBindings.Item(0).ReadValue()
                End If
            End If
     
        End Sub
    C'est loin d'être parfait mais ça a l'air de bien fonctionner.
    Par contre je trouve dommage qu'il n'existe pas d’événements de validation pour le DataGridView qui réagissent uniquement sur une vraie modification utilisateur et non sur perte de focus. Avec les contrôles simples c'est facile à faire, il suffit de désactiver la validation auto : et déclencher soit même la validation avec : L'exemple que j'ai donné révèle bien le problème que je rencontre si je ne fait pas cela. (Si l'utilisateur n'est pas l'auteur de la ligne ma procédure de validation affiche à chaque perte de focus : "Vous devez être l'auteur de la ligne pour la modifier !", hors ce message doit s'afficher uniquement si l'utilisateur modifie la ligne.

    Surtout n’hésitez pas si vous avez des remarques sur mon code, je programme tout seul donc tout est bon a prendre pour moi et je ne dispose d'aucun exemple au sujet de la validation. De plus je compte faire évoluer mon code petit a petit vers quelques choses de mieux en mieux structuré ou du moins bien séparer mon code en différentes couches (UI et BLL) pour commencer.
    L'utilisation des événements standard de validation à la place de ColumnChanging est une première étape à cela.

Discussions similaires

  1. Réponses: 4
    Dernier message: 24/09/2009, 19h21
  2. Annuler les modifications apportées à une table.
    Par PadawanDuDelphi dans le forum Bases de données
    Réponses: 5
    Dernier message: 18/10/2006, 09h26
  3. [VB.net 2003] Annuler les dernieres modifications d'une base de donnée
    Par winny107 dans le forum Accès aux données
    Réponses: 2
    Dernier message: 10/10/2006, 07h05
  4. Annuler les modifications dans un sous-formulaire
    Par soso78 dans le forum Access
    Réponses: 2
    Dernier message: 25/09/2006, 16h32
  5. [Utilisation] Récupérer les modifications depuis une date donnée
    Par Sapience dans le forum CVS
    Réponses: 1
    Dernier message: 15/02/2006, 12h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo