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:
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:
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:
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!
Partager