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

Windows Forms Discussion :

c#: DataGridView et l'evenement SelectionChanged appele plusieurs fois


Sujet :

Windows Forms

  1. #1
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 14
    Points : 12
    Points
    12
    Par défaut c#: DataGridView et l'evenement SelectionChanged appele plusieurs fois
    Bonjour a tous ,

    Je travaille sur un projet qui comporte au moins un controle DataGridView et une combobox (cb). J'utilise le DataGridView (dgv) controle de la facon suivante:

    En fonction de l'item selectionne par l'utilisateur dans la combobox:
    - j'envoie une requete a la base de donnees
    - je recupere le resultat d'une requete SQL dans une DataTable
    - je 'detache' l'evenement SelectionChanged de la dgv
    - j'attribue la DataTable a la propriete DataSource de la dgv
    - je recupere certaines valeurs de la premiere ligne de la dgv (que j'attribue a d'autres controles de types textbox)
    - j'indique que la premiere ligne de la dgv est selectionnee
    - je rattache l'evenement SelectionChanged de la dgv

    voici un exemple probablement plus parlant:
    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
     
     
    		String query = "";
    		DataTable dtFeature = null;
     
    		//populate datagridview                
    		dtFeature = GetDTfromQuery(query);
     
    		this.dgv_Mapping_Feature.SelectionChanged -= this.dgv_Mapping_Feature_SelectionChanged;
    		this.dgv_Mapping_Feature.DataSource = dtFeature.DefaultView;
    		//this.dgv_Mapping_Feature.SelectionChanged += this.dgv_Mapping_Feature_SelectionChanged;
     
    		if (dgv_Mapping_Feature.Rows.Count < 1)
    		return true;
     
    		//populate look-up fields
    		DGV_Mapping_Features_PopulateLookUpFields(0);
     
    		this.dgv_Mapping_Feature.Rows[0].Selected = true;    
    		this.dgv_Mapping_Feature.SelectionChanged += this.dgv_Mapping_Feature_SelectionChanged;
     
    private bool DGV_Mapping_Features_PopulateLookUpFields(int rowIdx)
    {
    	try
    	{
    		if (this.dgv_Mapping_Feature.Rows.Count < 1) return false;
    		//store current feature
    		m_CurrentFeature.ColumnValue = this.dgv_Mapping_Feature.Rows[rowIdx].Cells["COLUMN_VALUE"].Value.ToString();
    		m_CurrentFeature.DateUpdated = this.dgv_Mapping_Feature.Rows[rowIdx].Cells["UPDATED"].Value.ToString();
    	}
    	catch (Exception ex)
    	{
    		System.Diagnostics.Debug.WriteLine(ex.Message + "\n====\n" + ex.ToString());
    		return false;
    	}
     
    	return true;
    }
    Voici mon probleme:
    l'evenement SelectionChanged est appele plusieurs fois (au debut 7 et 2 fois par ligne en alternance). Je pensais que decrocher l'evenement avant de remplir ma dgv puis le rattacher une fois que tout est rempli resoudrait le probleme. mais non...
    j'ai ajoute des contraintes qui ont partiellement resolu le probleme (plutot masque en fait: l'appel est toujours fait maintes fois mais au moins il ne declanche pas l'action a chaque fois) . Mais il me reste toujours ces 2 a 3 appels qui passent les tests et que je ne controle pas.

    apres des heures de recherche, voici ce que j'ai trouve:

    - l'evenement est declanche automatiquement plusieurs fois de suite lorsque l'on remplit la dgv:
    1. lorsque la premiere ligne est ajoutee
    2. une fois qu'elle est ajoutee, quelque chose (la Form probablement) selectionne automatiquement la premiere ligne.

    - en controlant le call stack je me suis rendue compte qu'a chaque fois qu'un ligne est ajoutee a la dgv (lorsqu'elle est remplie) ca declenche alternativement les 2 suites d'evenements suivants:

    1. BindingContextChanged qui enchaine le renouvellement du contenu de la dgv et donc modifie la selection (par elimination si je comprends bien)
    2. Ajoute la ligne, ce qui appelle le SelectionChanged, puis reselectionne la premiere ligne ce qui appelle aussi l'evenement SelectionChanged

    j'avoue ne pas etre experte, du coup j'ai attache des captures d'ecran du Call Stack (au cas ou j'ai pas tout compris).

    Derniers details:
    1. j'utilise une classe particuliere pour la dgv:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        public class CustomDataGridView : System.Windows.Forms.DataGridView
        {
            public CustomDataGridView()
            {
                DoubleBuffered = true;
            }
        }
    ca me permet d'eviter des problemes d'affichage (flickering) lorsque la dgv est remplie.

    2. voici mon evenement:
    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
     
    private void dgv_Mapping_Feature_SelectionChanged(object sender, EventArgs e)
    {
    	try
    	{
    		//check the dgv has been populated (set back to nEabled= true once population done)
    		if (!this.dgv_Mapping_Feature.Enabled)
    			return;
    		if (this.dgv_Mapping_Feature.Rows == null || this.dgv_Mapping_Feature.Rows.Count < 1)
    			return;
    		// (multiSelect = false) => always only 1 element in the row collection
    		if (this.dgv_Mapping_Feature.SelectedRows.Count == 0)
    			return;
     
    		//get selected row index
    		int rowIdx = -1;
    		rowIdx = this.dgv_Mapping_Feature.SelectedRows[0].Index;
     
    		//select attr val look up for current row
    		DGV_Mapping_Features_PopulateLookUpFields(rowIdx);
     
    	}
    	catch (Exception ex)
    	{
    		System.Diagnostics.Debug.WriteLine(ex.Message + "\n====\n" + ex.ToString());
    	}
    }
    Avez-vous des suggestions quant a la solution a ce probleme?
    Comment faire en sorte que l'evenement ne soit declenche qu'une seule fois?

    J'ai pas vraiment envie de mettre des booleans partout pour controler ca.

    J'espere etre claire...

    Merci d'avance!
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 058
    Points : 12 093
    Points
    12 093

  3. #3
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 14
    Points : 12
    Points
    12
    Par défaut
    merci! j'vais creuser de ce côté là!

  4. #4
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 14
    Points : 12
    Points
    12
    Par défaut
    Bonjour,
    j'ai tente le BeginEdit/Endedit mais je ne dois pas l'utiliser correctement: j'obtiens l'erreur suivante:

    A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll
    Operation cannot be performed because there is no current cell. The CurrentCell property needs to be set first.
    ====
    System.InvalidOperationException: Operation cannot be performed because there is no current cell. The CurrentCell property needs to be set first.
    at System.Windows.Forms.DataGridView.BeginEdit(Boolean selectAll)

    Voici ce que j'ai tente de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     this.dgv_Mapping_Feature.BeginEdit(false);
     this.dgv_Mapping_Feature.DataSource = dtFeature.DefaultView;                
     this.dgv_Mapping_Feature.EndEdit();
    Je cherche a affecte un object DataTable a la propriete DataSource de la DataGridView (dgv). Evidemment, il n'y a pas de "CurrentCell" puisque j'affecte la source: j'ai rien dans la dgv.

    Quelqu'un sait-il comment faire?
    (i.e., comment peupler une dgv sans entrainer 7 puis 2 appels en alternance pour chacune des lignes ajoutees lorsqu'on affecte la DataTable a la propriete DataSource de la dgv?)

    Merci d'avance

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 058
    Points : 12 093
    Points
    12 093
    Par défaut
    "BeginInit" pas "BeginEdit"

  6. #6
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 14
    Points : 12
    Points
    12
    Par défaut
    arf... mauvaise lecture desolee...

    j'ai tente:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      ((System.ComponentModel.ISupportInitialize) (this.dgv_Mapping_Feature)).BeginInit();
      this.dgv_Mapping_Feature.DataSource = dtFeature.DefaultView;
    ((System.ComponentModel.ISupportInitialize)(this.dgv_Mapping_Feature)).EndInit();
    ca a pas l'air de resoudre le probleme...
    une idee du pourquoi?
    je manque une etape quelque part?

  7. #7
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 14
    Points : 12
    Points
    12
    Par défaut
    une solution simple et rapide en attendant de trouver mieux:

    utiliser les MouseEnter et MouseLeave events pour respectivement attacher et detacher l'evenement SelectionChanged. (soyez sur d'avoir enlever l'evenement du designer de la Form)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Faire appel plusieurs fois a un HTTPService ?
    Par piff62 dans le forum Flex
    Réponses: 3
    Dernier message: 08/07/2008, 11h32
  2. fonction rend visible champ appeler plusieurs fois
    Par djoyanna dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 09/06/2008, 18h34
  3. Init d'un servlet appelé plusieurs fois ?
    Par Eylir dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 18/03/2008, 16h35
  4. Réponses: 22
    Dernier message: 02/01/2007, 10h14
  5. [C# 2.0] Pourquoi le load est-il appelé plusieurs fois ?
    Par Worldofdada dans le forum ASP.NET
    Réponses: 9
    Dernier message: 14/09/2006, 09h34

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