OVH Cloud OVH Cloud

ComboBox et declencheur d'evenements

3 réponses
Avatar
JFGerard
Bonjour a tous

Quand on remplit, DYNAMIQUEMENT, une ComboBox avec une datasource venant
d'une BindingSource (dataadapter, et tout le reste), un premier groupe
d'evenement (TextChanged, SelectedValueChanged, SelectedItemChanged) est
déclenché lors de la liaison, puis, quand on initialise le DisplayMember avec
le nom du champ a visualiser, rebelote, et comme je ne veux pas voir le
premier element de la liste par defaut dans le texte de la CB, je mets le
SelectedItem a Nothing, et paf, nouvelle sequence d'evenements.

Et comme evidemment, dans la procedure qui traite SelectedIndexChanged, le
code positionne d'autres controles, a chaque fois, vingt millions
d'evenements apparaissent, dans un ordre qui releve d'une joyeuse pagaille !!!
et aussi quand on casse la liaison a la datasource, sur un Dispose par
exemple.

Question :
Y a-t-il un moyen de neutraliser (au moins) ou d'eliminer (au mieux) tous
ces evenements parasites qui apparaissent dans les phases d'initialisation,
pour ne conserver que les evenements utiles lorsque l'operateur clique sur la
liste de la combo, l'ouvre et selectionne un element ?
J'ai tenté la detection de l'evenement Click (dont la Combo herite, d'après
la doc), mais ca ne reagit pas.
Ca semble un truc bete, mais la "Doc pour les Nuls" n'aborde evidemmnet pas
ces concepts et la "Doc pour les Pros" est tellement touffue que je n'ai rien
trouvé/compris !!!

Merci (a ceux qui m'aime assez pour repondre !!)

JFG

3 réponses

Avatar
Millox Frédéric
Bonjour,

Quand vous parlez de remplir la combobox DYNAMIQUEMENT, est-ce-que ça veut
dire que vous l'initialisez dans le code ??? Si oui, le seul moyen que je
connaisse ( il y en peût-être d'autres... ) est de rajouter une variable
globale.

Petit exemple :

Public Class Form1
Inherits System.Windows.Forms.Form

Private _OkInitComboBox As Boolean

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.ComboBox1 = New System.Windows.Forms.ComboBox
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(64, 16)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'ComboBox1
'
Me.ComboBox1.Location = New System.Drawing.Point(24, 56)
Me.ComboBox1.Name = "ComboBox1"
Me.ComboBox1.Size = New System.Drawing.Size(160, 21)
Me.ComboBox1.TabIndex = 1
Me.ComboBox1.Text = ""
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(200, 101)
Me.Controls.Add(Me.ComboBox1)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim dt As DataTable
Dim row As DataRow

dt = New DataTable
dt.Columns.Add("Id", System.Type.GetType("System.Int32"))
dt.Columns.Add("Prenom", System.Type.GetType("System.String"))

row = dt.NewRow
row("Id") = 1
row("Prenom") = "toto"
dt.Rows.Add(row)

row = dt.NewRow
row("Id") = 2
row("Prenom") = "titi"
dt.Rows.Add(row)

_OkInitComboBox = False
With ComboBox1
.DataSource = dt
.DisplayMember = "Prenom"
.ValueMember = "Id"
.Text = "Sélectionner un prénom"
End With
_OkInitComboBox = True
End Sub

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal
e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
If _OkInitComboBox Then MsgBox(ComboBox1.SelectedValue.ToString)
End Sub
End Class

J'espère que cela vous aura aidé.

Cordialement.

--
fmillox


"JFGerard" a écrit :

Bonjour a tous

Quand on remplit, DYNAMIQUEMENT, une ComboBox avec une datasource venant
d'une BindingSource (dataadapter, et tout le reste), un premier groupe
d'evenement (TextChanged, SelectedValueChanged, SelectedItemChanged) est
déclenché lors de la liaison, puis, quand on initialise le DisplayMember avec
le nom du champ a visualiser, rebelote, et comme je ne veux pas voir le
premier element de la liste par defaut dans le texte de la CB, je mets le
SelectedItem a Nothing, et paf, nouvelle sequence d'evenements.

Et comme evidemment, dans la procedure qui traite SelectedIndexChanged, le
code positionne d'autres controles, a chaque fois, vingt millions
d'evenements apparaissent, dans un ordre qui releve d'une joyeuse pagaille !!!
et aussi quand on casse la liaison a la datasource, sur un Dispose par
exemple.

Question :
Y a-t-il un moyen de neutraliser (au moins) ou d'eliminer (au mieux) tous
ces evenements parasites qui apparaissent dans les phases d'initialisation,
pour ne conserver que les evenements utiles lorsque l'operateur clique sur la
liste de la combo, l'ouvre et selectionne un element ?
J'ai tenté la detection de l'evenement Click (dont la Combo herite, d'après
la doc), mais ca ne reagit pas.
Ca semble un truc bete, mais la "Doc pour les Nuls" n'aborde evidemmnet pas
ces concepts et la "Doc pour les Pros" est tellement touffue que je n'ai rien
trouvé/compris !!!

Merci (a ceux qui m'aime assez pour repondre !!)

JFG




Avatar
JFGerard
Bonjour

Ouai, super sympa, ca marche ..... BONNE Idee ....

un peu lourd : une variable globale par CB plus le test dans toutes les
procedures d'evenements type SelectedIndex/Value/Text_Changed
mais ca marche !!!

evidemment après, il faut choisir le bon endroit pour positionner la
variable InitOK de facon a ne pas perdre des evenements de mises a jour de la
liste, mais c'est bon.

MERCI Beaucoup.

Je suis quand meme surpris que cela ne fasse pas partie des caracteristiques
de base de la Combo, de pouvoir desactiver les evenements pendant la phase
d'initialisation, mais ... si notre ami Bill en a decidé ainsi !!!!

Je me demande si en créant un objet dérivé de la CB ayant cette
caractéristique, on ne pourrait pas avoir une CB plus "intelligente" ..... je
vais regarder cela ...

Merci encore
JFG

PS : oui effectivement, par "remplir la Combobox dynamiquement", je voulais
bien dire "l'initialiser dans le code", au cas particulier par une
BindingSource (MyCB.datasource = MyBindingSource) venant d'un dataAdapter
(Mydataadapter.fill(myDataSet)) venant d'un dataset venant d'une Base de
donnees, mais la problematique me semble la meme qu'avec le bout de code
ci-dessous.

A que plus ..... peut-etre.
---------------------------------------------------------

"Millox Frédéric" a écrit :

Bonjour,

Quand vous parlez de remplir la combobox DYNAMIQUEMENT, est-ce-que ça veut
dire que vous l'initialisez dans le code ??? Si oui, le seul moyen que je
connaisse ( il y en peût-être d'autres... ) est de rajouter une variable
globale.

Petit exemple :

Public Class Form1
Inherits System.Windows.Forms.Form

Private _OkInitComboBox As Boolean

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.ComboBox1 = New System.Windows.Forms.ComboBox
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(64, 16)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'ComboBox1
'
Me.ComboBox1.Location = New System.Drawing.Point(24, 56)
Me.ComboBox1.Name = "ComboBox1"
Me.ComboBox1.Size = New System.Drawing.Size(160, 21)
Me.ComboBox1.TabIndex = 1
Me.ComboBox1.Text = ""
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(200, 101)
Me.Controls.Add(Me.ComboBox1)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim dt As DataTable
Dim row As DataRow

dt = New DataTable
dt.Columns.Add("Id", System.Type.GetType("System.Int32"))
dt.Columns.Add("Prenom", System.Type.GetType("System.String"))

row = dt.NewRow
row("Id") = 1
row("Prenom") = "toto"
dt.Rows.Add(row)

row = dt.NewRow
row("Id") = 2
row("Prenom") = "titi"
dt.Rows.Add(row)

_OkInitComboBox = False
With ComboBox1
.DataSource = dt
.DisplayMember = "Prenom"
.ValueMember = "Id"
.Text = "Sélectionner un prénom"
End With
_OkInitComboBox = True
End Sub

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal
e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
If _OkInitComboBox Then MsgBox(ComboBox1.SelectedValue.ToString)
End Sub
End Class

J'espère que cela vous aura aidé.

Cordialement.

--
fmillox


"JFGerard" a écrit :

> Bonjour a tous
>
> Quand on remplit, DYNAMIQUEMENT, une ComboBox avec une datasource venant
> d'une BindingSource (dataadapter, et tout le reste), un premier groupe
> d'evenement (TextChanged, SelectedValueChanged, SelectedItemChanged) est
> déclenché lors de la liaison, puis, quand on initialise le DisplayMember avec
> le nom du champ a visualiser, rebelote, et comme je ne veux pas voir le
> premier element de la liste par defaut dans le texte de la CB, je mets le
> SelectedItem a Nothing, et paf, nouvelle sequence d'evenements.
>
> Et comme evidemment, dans la procedure qui traite SelectedIndexChanged, le
> code positionne d'autres controles, a chaque fois, vingt millions
> d'evenements apparaissent, dans un ordre qui releve d'une joyeuse pagaille !!!
> et aussi quand on casse la liaison a la datasource, sur un Dispose par
> exemple.
>
> Question :
> Y a-t-il un moyen de neutraliser (au moins) ou d'eliminer (au mieux) tous
> ces evenements parasites qui apparaissent dans les phases d'initialisation,
> pour ne conserver que les evenements utiles lorsque l'operateur clique sur la
> liste de la combo, l'ouvre et selectionne un element ?
> J'ai tenté la detection de l'evenement Click (dont la Combo herite, d'après
> la doc), mais ca ne reagit pas.
> Ca semble un truc bete, mais la "Doc pour les Nuls" n'aborde evidemmnet pas
> ces concepts et la "Doc pour les Pros" est tellement touffue que je n'ai rien
> trouvé/compris !!!
>
> Merci (a ceux qui m'aime assez pour repondre !!)
>
> JFG
>
>


Avatar
jerome crevecoeur
Pour ma part, j'initialisement seulement une variable
Private m_isFormloading as boolean

que je teste dans chaque procédure événementielle.

Sinon faut regarder du coté des événements validated ...

JFGerard a écrit :
Bonjour

Ouai, super sympa, ca marche ..... BONNE Idee ....

un peu lourd : une variable globale par CB plus le test dans toutes les
procedures d'evenements type SelectedIndex/Value/Text_Changed
mais ca marche !!!

evidemment après, il faut choisir le bon endroit pour positionner la
variable InitOK de facon a ne pas perdre des evenements de mises a jour de la
liste, mais c'est bon.

MERCI Beaucoup.

Je suis quand meme surpris que cela ne fasse pas partie des caracterist iques
de base de la Combo, de pouvoir desactiver les evenements pendant la ph ase
d'initialisation, mais ... si notre ami Bill en a decidé ainsi !!!!

Je me demande si en créant un objet dérivé de la CB ayant cette
caractéristique, on ne pourrait pas avoir une CB plus "intelligente" ..... je
vais regarder cela ...

Merci encore
JFG

PS : oui effectivement, par "remplir la Combobox dynamiquement", je vou lais
bien dire "l'initialiser dans le code", au cas particulier par une
BindingSource (MyCB.datasource = MyBindingSource) venant d'un dataAda pter
(Mydataadapter.fill(myDataSet)) venant d'un dataset venant d'une Base de
donnees, mais la problematique me semble la meme qu'avec le bout de cod e
ci-dessous.

A que plus ..... peut-etre.
---------------------------------------------------------

"Millox Frédéric" a écrit :

Bonjour,

Quand vous parlez de remplir la combobox DYNAMIQUEMENT, est-ce-que ç a veut
dire que vous l'initialisez dans le code ??? Si oui, le seul moyen que je
connaisse ( il y en peût-être d'autres... ) est de rajouter une va riable
globale.

Petit exemple :

Public Class Form1
Inherits System.Windows.Forms.Form

Private _OkInitComboBox As Boolean

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boole an)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Des igner
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents ComboBox1 As System.Windows.Forms.ComboBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.ComboBox1 = New System.Windows.Forms.ComboBox
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(64, 16)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'ComboBox1
'
Me.ComboBox1.Location = New System.Drawing.Point(24, 56)
Me.ComboBox1.Name = "ComboBox1"
Me.ComboBox1.Size = New System.Drawing.Size(160, 21)
Me.ComboBox1.TabIndex = 1
Me.ComboBox1.Text = ""
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(200, 101)
Me.Controls.Add(Me.ComboBox1)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e A s
System.EventArgs) Handles Button1.Click
Dim dt As DataTable
Dim row As DataRow

dt = New DataTable
dt.Columns.Add("Id", System.Type.GetType("System.Int32"))
dt.Columns.Add("Prenom", System.Type.GetType("System.String"))

row = dt.NewRow
row("Id") = 1
row("Prenom") = "toto"
dt.Rows.Add(row)

row = dt.NewRow
row("Id") = 2
row("Prenom") = "titi"
dt.Rows.Add(row)

_OkInitComboBox = False
With ComboBox1
.DataSource = dt
.DisplayMember = "Prenom"
.ValueMember = "Id"
.Text = "Sélectionner un prénom"
End With
_OkInitComboBox = True
End Sub

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal
e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
If _OkInitComboBox Then MsgBox(ComboBox1.SelectedValue.ToStrin g)
End Sub
End Class

J'espère que cela vous aura aidé.

Cordialement.

--
fmillox


"JFGerard" a écrit :

Bonjour a tous

Quand on remplit, DYNAMIQUEMENT, une ComboBox avec une datasource ven ant
d'une BindingSource (dataadapter, et tout le reste), un premier group e
d'evenement (TextChanged, SelectedValueChanged, SelectedItemChanged) est
déclenché lors de la liaison, puis, quand on initialise le Displa yMember avec
le nom du champ a visualiser, rebelote, et comme je ne veux pas voir le
premier element de la liste par defaut dans le texte de la CB, je met s le
SelectedItem a Nothing, et paf, nouvelle sequence d'evenements.

Et comme evidemment, dans la procedure qui traite SelectedIndexChange d, le
code positionne d'autres controles, a chaque fois, vingt millions
d'evenements apparaissent, dans un ordre qui releve d'une joyeuse pag aille !!!
et aussi quand on casse la liaison a la datasource, sur un Dispose pa r
exemple.

Question :
Y a-t-il un moyen de neutraliser (au moins) ou d'eliminer (au mieux) tous
ces evenements parasites qui apparaissent dans les phases d'initialis ation,
pour ne conserver que les evenements utiles lorsque l'operateur cliqu e sur la
liste de la combo, l'ouvre et selectionne un element ?
J'ai tenté la detection de l'evenement Click (dont la Combo herite, d'après
la doc), mais ca ne reagit pas.
Ca semble un truc bete, mais la "Doc pour les Nuls" n'aborde evidemmn et pas
ces concepts et la "Doc pour les Pros" est tellement touffue que je n 'ai rien
trouvé/compris !!!

Merci (a ceux qui m'aime assez pour repondre !!)

JFG