Permettre qu'après un Dataset.AcceptChanges () seules les lignes après la ligne

Signaler
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010
-
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010
-
Bonjour,

J'utilise Visual Basic 2008 Express.

Dans un DataGridView, après avoir supprimié une ligne, j'exécutel'ordre Me.DataSet.AcceptChanges().
L'ordre est correctement exécuté, toutefois cela a pour effet de ramener la ligne suivant la ligne supprimée en avant dernière position du tableau visible à l'écran.
Je souhaiterais que les lignes précédents la ligne supprimée restent à la même places et que les lignes qui la suivent remontes d'un cran.

Y-a-t il une option pour cela ?

J'ai tenté d'utiliser le contrôle : DataGridView.FirstDisplayCell.RowIndex, mais la modification de sa valeur n'est pas autorisée car RowIndex est en ReadOnly, peut-on autoriser sa modification si oui comment ?


Cordialement
Philippe
A voir également:

15 réponses

Messages postés
1207
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
4 juin 2016
10
Bonjour,

Je ne connais pas .NET, mais si j'ai bien compris tu veux que la ligne supprimée reste en fait en blanc dans ton DataGridView.

A ma connaissance ce n'est pas possible sur un Recordset Connecté (on ne peut tout simplement pas avoir d'enregistrement vide dans une table.

La solution passerait par un recordset déconnecté (chaîne de connexion = "") avec ajout d'une colonne indiquant que l'enregistrement est supprimé et avec une routine vidant toutes les autres colonnes.

Mais regarde si le jeu en vaut la chandelle puisqu'il faut gérer 2 recordsets en // (1 connecté et 1 déconnecté).

Attention que je te donne marche sans problème en VB6 + ADO 2.x, à voir en .NET et à réserver pour de petits recordsets de préférence.

Calade
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
37
Salut,

Moi non plus je n'ai pas bien compris, en gros quand tu vires une ligne, les autres lignes de ton DataGridView sont désordonnées ? Ou c'est simplement la sélection (surlignage bleu) qui change de position ?

Question, quel est ta requête SELECT pour le remplissage ? As-tu une clause "ORDER BY" ?

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010

Merci pour vos réponses.

Je crois que je me suis mal fait comprendre, mon soucis est juste un problème de présentation.
La ligne qui suit la ligne supprimée est systématiquement ramenée en avant dernière ligne dans l'écran (datagridview), alors que je préfererais que ce soit toutes les lignes qui suivent qui remontent, autrement dit que les lignes qui précédent la ligne supprimée ne bougent pas.
Je vais tenter de l'illustrer par une exemple visuel.
Admettons que mon écran comporte un datagridview de 5 lignes, et que mon dataset (la table de données) 10 lignes.
Contenu écran avant la suppression :
Ligne 4
Ligne 5 <= ligne à supprimer
Ligne 6
Ligne 7
Ligne 8

Je supprime la ligne 5 :
Ecran après la suppression
Ligne 2
Ligne 3
Ligne 4
Ligne 6 <= ligne qui suit la supprimée ramenée en avant dernière position, les lignes qui précèdent coulissent vers le bas !
Ligne 7

Ce que je souhaite après suppression
Ligne 4
Ligne 6 <= les lignes qui suivent la supprimée remontent, cells qui précédent ne bougent pas
Ligne 7
Ligne 8
Ligne 9

Un solution, me semble-t-il, serait de forcer, après la suppression, le contrôle DataGridView.FirstDisplayCell.RowIndex à la valeur RowIndex de la ligne 4 , mais je ne peux pas car il est en ReadOnly, et je ne sais pas comment le rendre modifiable, si c'est possible.


A+
Messages postés
1207
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
4 juin 2016
10
Bonjour,

Comme je te l'ai dit, je ne connais pas .NET, mais je pense que c'est ton recordset sous-jacent qui est en read-only.

En ADO 2.x, tu peux regarder les propriétés Mode de ta connexion ou éventuellement la propriété CursorType de ton recordset.
Je ne connais pas les équivalents en ADO .NET mais tu devrais les trouver assez facilement.


Calade
Messages postés
140
Date d'inscription
mardi 25 novembre 2003
Statut
Membre
Dernière intervention
1 novembre 2010
6
Bonjour,
Votre Datagridview est normalement "alimenter" par une source de données avec un code qui ressemble à ça :

        BindingSource.DataSource1 = Dataset1.Tables("******")
        DataGridView1.DataSource = BindingSource1

A tester:
 BindingSource1.EndEdit()

plutôt que :
Dataset1.AcceptChanges()
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010

J'ai essayé la proposition de Chritsoni, mais sans le code Daset1.AcceptChanges () la ligne n'est pas supprimée du dataset, ce qui m'oblige à gérer l'état chaque ligne pour ignorer celle qui sont supprimées.

Je vais explorer la proposition de Calade, pour l'instant je n'ai pas trouvé la propriété CursorType du recordset.
Messages postés
140
Date d'inscription
mardi 25 novembre 2003
Statut
Membre
Dernière intervention
1 novembre 2010
6
Je ne sais pas si le dataset peut être mis à jour à la fin des ajouts ou suppressions effectués sur le datagridview.
Si oui, à tester :
Créer une copie du dataset qui enregistre les modifs
                Dim dsTemp As New DataSet
                dsTemp = ds.GetChanges()

et une procédure qui est déclenchée en fin de traitement pour apporter les modif au dataset d'origine :
                ds.Clear()
                ds.Merge(dsTemp)
Messages postés
1207
Date d'inscription
dimanche 20 avril 2003
Statut
Membre
Dernière intervention
4 juin 2016
10
Comme je te l'ai dit cette propriété est en ADO 2.x, elle porte peut-être un autre nom en .NET.

Regarde aussi la propriété Mode (ou son équivalent) de ta connexion. Elle définit so mode (!): Read, Write, Read/Write, etc...


Calade
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
37
christoni> Si tu veux mon avis tu te prend la tête pour un détail, du moment que ta ligne est supprimé et que tes lignes sont visibles...

Fin bon, juste comme ca pour voir, essaye de mettre assez d'élément dans ta table pour avoir un défillement du double de la taille de ton DatGrid. Supprimer le dernier élément, celle-ci revient elle en début de liste ?

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010

>> Mayzz, tu n'as pas tort c'est un détail, mais bon c'est aussi pour comprendre le mécanisme.
Lorsque la table contient plus d'une page affichée à l'écran, le résultat est le même.
Il n'y a que losrque la table contient moins d'une page que cela fait ce que je veux, évidemment les lignes ne peuvent pas descendre, cela ferait un vide en haut de page !

Ce qui m'intéresse notamment serait de pouvoir décider quelle ligne de mon dataset je veux afficher dans la 1ère ligne affichée à l'écran.


Je vais essayer les propositions indiquées.

en tout cas merci à tous pour votre aide.
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
37
OK, c'était pour vérifier, et c'est donc bien ca.

Comme je ne passe jamais par le même événement que toi pour la validation (DataSet.AcceptChanges) je ne pouvais pas savoir.

Apparement l'Adapter du DataSet, utilise à nouveau la fonction Fill (via la requête SQL SELECT, du coup les Adapter on le paramètre ClearBeforeFill sur True, ce qui est plutot logique mais entraine un vidage complet de la table et un remplissage, l'index du row en cour se perdant dans l'histoire..

Il te faudra jouer avec DataGridView.CurrentRow mais comme celui-ci est aussi readonly utilise la propriété DataGridView.CurrentCell qui elle ne l'est pas pour définir la séléction courrante. Exemple concret :

DataGridView1.CurrentCell = DataGridView1.Row(IndexDeLaLigne).Cell(0)

Il existe aussi les propriétés SelectedCells et SelectedRows mais elle sont toutes deux aussi readonly et faites pour consulter le nombre de lignes sélectionnés lors d'un Multiselect.

Pour fonctionner la méthode que j'utilise requière que la propriété SelcetionMode soit sur FullRowSelect.

Aussi tu peux enregistrer l'index de la ligne sélectionner avant la mise à jour de ton DataSet, et la restituer dans l'événement DataBindingComplete du DataGridView

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Messages postés
140
Date d'inscription
mardi 25 novembre 2003
Statut
Membre
Dernière intervention
1 novembre 2010
6
Mayzz : ce sont de bonnes solutions de contournement, mais elles n'éviteront pas l'effet de scintillement (terme impropre)
Càd qu'un affichage sera suivi d'un autre (pénible selon son processeur)(c'est vrai que je suis un EDM).
J'en reviens à la question de savoir si il est primordiale d'avoir un Dataset à jour immédiatement.
Si c'est non, alors l'enregistrer à la fin de la manip et le problème est résolu.
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
37
Techniquement ce n'est pas possible car les conteneurs de données (DataTable, DataSet) sont en quelque sorte le "cache" de ta base, mais c'est un autre objet qui s'ocupe d'effectuer les requêtes, d'insertion, de modification et de suppression. Ainsi lors ce que tu supprime une ligne de ton Dataset la ligne est d'abord supprimé de ta table physique puis la DataTable est vidé et remplie depuis cette table.

Une question me viens à l'esprit, un DataTable possède des Row et ces rows des RowState (Added, Deleted, Detached, Modified, Unchanged) ceux-ci mêmes sont des repères pour savoir lors de l'appel à AcceptChange si les Row doivent être modifier ou non, ce qui contredit totalement le principe énuméré plus haut.

Je pense qu'il faut essayer de Mettre la Propriété ClearBeforFill de l'adapter de ton DataSet pour voir, dans le pire des cas cela doublera les lignes à chaque mise à jour et provoquera surement une erreur de doublon d'ID.

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010

J'ai essayé en précisant la propriété ClearBeforFill (à true et false) cela ne fait pas de différence visible.

Mais par ailleurs je viens de comprendre que je n'utilise pas AcceptChanges () à bon escient.
Son utilisation avant UPDATE a pour effet que les changements (insert,upadte, delete) effectués dans le DATASET ne sont plus considérés comme des changements. Ils sont bien pris en compte et visibles dans le DataGrid, mais au moment de faire l'update du DataAdaptater dans la base, aucun changement n'y est répercuté. Du reste l'update effectue implicitement le AcceptChanges.

Si je veux continuer à utiliser l'AcceptChanges je devrais utiliser un dataset miroir comme le suggère Christoni, un 1er dataset dans lequel j'effectue les modifs avec AcceptChanges lié au DataGrid et un second sans l'AcceptChanges, à partir duquel je ferais l'update,


J'avais décidé d'utiliser l'AcceptChanges pour éviter de devoir gérer l'état de chaque row dans le dataset.
Car sans AcceptChanges, les row "Deleté" sont toujours présents dans le dataset et si on tente d'y accèder ça plante, ce qui oblige de tester le code état d'un row avant d'y accéder. Ce que je voulais éviter car cela me semblait lourd.

Je crois que je vais devoir revoir ma façon de gérer les maj du DATASET, l'avantage est qu'en renonçant à AcceptChanges(), l'affichage correspond à mes attentes.


Je reviendrai vous expliquer la solution que j'aurai adopté lorsque cela fonctionnera.


Encore merci à tous
Philippe
Messages postés
6
Date d'inscription
jeudi 18 mars 2010
Statut
Membre
Dernière intervention
19 juin 2010

Bonjour,

Voilà la solution que j'ai trouvé :

Avant de supprimer la ligne je sauvegarde le n° de ligne du haut de la page :
RowPremièreLigne = My.DataGridView.FirstDisplayedCell.RowIndex

Après la suppression je restaure le n° de la ligne :
My.DataGridView.FirstDisplayedScrollingRowIndex = RowPremièreLigne

Par ailleurs j'ai repris l'idée de Christoni d'un dataset miroir.
En effet lorsqu'on supprime une ligne dans un dataset, si on veut que le datagridview auquel il est lié soit en phase avec lui il faut faire un My.Dataset.AcceptChanges ().
Faute de quoi les lignes supprimées ne se voient plus dans le datagridView mais sont toujours dans le dataset, pas évident ensuite de synchroniser le n° de ligne des deux objets.
Mais l'acceptChanges a l'inconvénient de ne plus pouvoir répercuté les maj dans la base depuis ce dataset. J'ai donc créé un second dataset miroir auquel je fais subir toutes les maj mais sans l'AcceptChanges, et c'est à partir ce dataset miroir que je fais l'update de la base, et l'autre sert de lien avec le datagridView

Je ne sais pas si c'est une bonne solution , mais elle a au moins l'avantage de fonctionner.

Note : Pour éviter le dataset miroir j'aurai pu faire l'update de la base à chaque maj, mais j'ai fait le choix de ne faire l'update de la base que sur demande avec un choix "enregistrer". Cela permet de renoncer à ses maj si nécessaire.

Cordialement
Philippe