Empêcher le clic sur un onglet (tabpage) d?un tabcontrol

Contenu du snippet

Bonjour à tous,

Voilà, suite à un problème que j?ai rencontré et auquel j?ai finalement trouvé une solution, je me permets de poster une source ici, car je pense que ma solution pourra (je l?espère !) aider également d?autres personnes.

En fait, le problème pourrait se résumer ainsi :
« Comment faire pour empêcher l?utilisateur de cliquer sur une page (TabPage) d?un TabControl ? »

J?ai recherché des solutions sur ce site et n?ai malheureusement rien trouvé de satisfaisant pour résoudre mon problème particulier. (Bon, ok, j?avoue, mon temps de recherche se compte plus en minutes qu?en heures, et si j?avais approfondi un peu plus ma recherche j?aurai peut-être trouvé une solution, m?enfin...)

C?est pourquoi je poste ici ma 1ère source, alors soyez indulgents svp ! ;)

Je suis loin d?être une professionnelle, je ne suis qu?étudiante ; donc il est fort possible que ma solution soit loin d?être la plus adaptée, ni la plus efficace ; mais en l?occurence, elle fonctionne, et c?est déjà pas mal ! ;)

Pour expliquer plus clairement le problème je vais vous donner l?exemple de mon application.

Suite à un exercice donné en cours, j?ai créé une application toute simple permettant d?ajouter un employé, d?afficher les informations concernant tous les employés et de calculer leur salaires. Le but de l?exercice était juste de nous familiariser avec les collections (arraylist) ainsi que la lecture/écriture de fichiers avec les classes StreamReader et StreamWriter.

Je n?ai pas besoin de rentrer plus dans les détails car cela n?aura pas d?intérêt pour la suite ; mais en gros, j?ai décidé d?utiliser le composant « TabControl » dans « Windows Forms » (petite précision : j?utilise la version anglaise de Visual Studio et je ne suis pas sûre de la traduction pour la version française donc je laisse comme ça, mais je pense que vous voyez de quoi je parle) pour mon « Menu ».
J?ai ajouté 4 « TabPages » (onglets) dans ce TabControl :
- tabHome (la page d?accueil),
- tabAdd (pour ajouter un employé),
- tabDisplay (pour afficher les informations concernant un employé en le choisissant dans une liste, et pour le modifier/supprimer),
- tabPayroll (pour afficher le salaire de chaque employé dans une liste)

Mon problème est survenu lors de la programmation du bouton « Modify » pour modifier les informations d?un employé. En effet, un clic sur le bouton modifier provoque la disparition de celui-ci, l?apparition de boutons « Save » et « Cancel », la possibilité d?écrire dans les textbox et l?interdiction de cliquer ailleurs que sur Sauvegarder ou Annuler.

D?où mon problème : l?utilisateur se trouvant dans la page tabDisplay décide de sélectionner un employé et de le modifier, mais au lieu de choisir Sauvegarder ou annuler, il clique finalement sur un autre onglet de mon menu.
Je ne voulais pas que cela soit possible avant d?avoir soit sauvegardé, soit annulé les modifications éventuelles.

Durant mes recherches pour résoudre le problème et ainsi empêcher le clic sur un onglet (et donc l?affichage de celui-ci) j?ai trouvé diverses solutions :
> mettre la propriété « enabled » de la page onglet à « false »
Résultat : on peut toujours cliquer sur l?onglet et la page s?affiche, mais tous ses composants sont « disabled ». => ne marche pas
> appeller la procédure « Hide » ou bien mettre la propriété « Visible » à « false » de la page onglet
Résultat : on peut toujours cliquer sur l?onglet, mais tous les composants de cette page ont disparus. => ne marche pas
> utiliser la méthode « Remove » du TabControl pour enlever la TabPage, puis « Add » pour la rajouter une fois les modifications faites
Résultat : supprime carrément la page et en rajoute une vierge => ne marche pas DU TOUT
> sélectionner la TabPage sur laquelle on veut rester avec TabControl.SelectedTab
Résultat : y?a de l?idée, (et d?ailleurs, c?est ce qui m?a mis sur la voie) mais incomplet

Voici donc, après tout ce blablabla, MA solution.
L?idée est de déclarer une variable globale (c?est à dire, au début du code et qui pourra être utilisée partout dans le code) booléenne, qui en gros permettra oui ou non de cliquer sur d?autres onglet que celui où je suis.

Source / Exemple :


'declaration de la variable globale booléenne = vrai par défaut car normalement on a le droit de cliquer sur les pages

Private allowClickTab As Boolean = True

'procédure événementielle "SelectedIndexChanged" de mon objet TabControl (que j?ai appellé tabPayrollArray) qui est appellée lorsque l?on choisit/clique sur un onglet dans le tabcontrol

Private Sub tabPayrollArray_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tabPayrollArray.SelectedIndexChanged

'si l?onglet sélectionné est soit Home, Add, OU Payroll, ET que ma variable booléenne « allowClickTab » est à « False »
'If ((tabPayrollArray.SelectedTab Is tabHome) Or (tabPayrollArray.SelectedTab Is tabAdd) Or (tabPayrollArray.SelectedTab Is tabPayroll)) 
'PRECISION: les noms de tabpages que j?ai utilisé dans ma condition (tabHome, etc) sont bien évidemment les noms de toutes mes pages/onglets AUTRE que celui où l?utilisateur doit rester, et il faudra donc adapter votre code en fonction de vos propres TabPages et de celle(s) dont vous voulez empêcher le clic. 

'modification de ma condition suite a un commentaire de Diesel78, c'est mieux et + simple avec un If Not; merci encore! :)
If (Not tabPayrollArray.SelectedTab Is tabDisplay) And allowClickTab = False Then

'Resélectionne l?onglet Display c?est-à-dire la page dans laquelle je veux rester. En clair, si on sélectionne un autre onglet, il reselectionnera automatiquement l?onglet où l?on veut rester. 

tabPayrollArray.SelectedTab = tabDisplay

'affiche un message indiquant à l?utilisateur qu?il doit cliquer d?abord sur Save ou Cancel avant de pouvoir cliquer ailleurs

MsgBox("Please save or cancel your modifications before leaving this page", MsgBoxStyle.Information, "Modify an Employee")

End If

End Sub

'Enfin, il ne reste plus qu?à décider quand on veut empêcher le clic sur les autres onglets.

'Dans mon example, c?est après avoir cliqué sur le bouton « Modifier » que je veux empecher un clic sur un autre onglet.
'Dans l?évènement clic de mon bouton, je dois juste rajouter : 

Private Sub btnDisplayModify_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisplayModify.Click
'met à false ma variable booléenne 
allowClickTab = False
End Sub

'Ceci va permettre de rendre ma condition dans ma procédure TabControl.SelectedIndexChanged VRAIE et donc empêcher le clic 

'Pour permettre, une fois la sauvegarde ou annulation, de pouvoir cliquer de nouveau sur les onglets, il faut attribuer la valeur TRUE à ma variable dans les événements click de mes boutons Save et Cancel

Private Sub btnDisplayCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisplayCancel.Click
'met à true ma variable booléenne 
allowClickTab = True
End Sub

Private Sub btnDisplaySave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisplaySave.Click
'met à true ma variable booléenne 
allowClickTab = True
End Sub

'NOTE: Dans mon programme, cliquer sur Save ou Cancel permet également de rafficher le bouton Modifier et de cacher Save et Cancel. Inversement, cliquer sur Modifier permet d'afficher Save et Cancel et de cacher Modifier. Je n'ai pas rajoute ici le code car il n'est pas necessaire ici, mais pour expliquer brievement, il suffit d'utiliser la fonction Hide et Show des boutons que l'on veut afficher ou cacher dans l'evenement Click du bouton correspondant.

Conclusion :


VOILA, C?EST FINI, ENJOY!

Ce n?est pas plus compliqué (n?ayons pas peur des mots, c?est même très simple) que cela et ça permet d?empêcher un utilisateur de cliquer sur d?autres onglets quand il doit d?abord effectuer une action précise à l?intérieur d?un onglet.

Bon l?inconvénient est que ça oblige à passer par l?intermédiaire d?une variable globale, m?enfin, à l?heure actuelle je n?ai pas encore trouvé de meilleure solution.

N?hésitez pas à poser vos questions, écrire d?éventuels commentaires/critiques et à me demander plus d?explications ou de précisions si jamais vous avez besoin ; j?ai essayé d?être claire mais ce n?est peut-être pas suffisant...

Et si jamais vous avez une autre solution, merci de me l?indiquer, ça pourra toujours m?aider !

Merci de votre attention, et en espérant avoir pu vous donner un petit conseil, et peut-être même vous avoir aidé à résoudre un de vos problèmes, je vous souhaite une bonne prog avec notre ami VB.NET ! ;)

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.