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 Presentation Foundation Discussion :

DropDown Button, Popup et perte de focus


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 24
    Par défaut DropDown Button, Popup et perte de focus
    Bonjour,

    j'ai créé un DropDownButton sur la base d'un Button et quand je clique sur le Button, une popup apparait.
    Cette popup à une liste de ToggleButton (mais qui me servent complètement à autre chose).

    Pour l'apparition de la popup ça marche nickel. Par contre j'ai un peu plus de soucis pour la faire disparaitre. L'idée c'est que je voudrais avoir un comportement comme un ContextMenu à savoir disparition quand on clique un élément ou quand on clique en dehors.

    Le problème si je surcharge la méthode OnLostFocus de ma popup, étant donné que je perds le focus quand je clique sur l'un de mes ToggleButton, l'action du clic sur le ToggleButton n'a pas le temps de se réaliser puisque la popup disparait avant.

    Une idée ?

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    2 210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 210
    Par défaut
    Salut,

    Essaie de voir si des évènements types PreviewMouseDown pour la souris et PreviewGotKeyboardFocus pour le clavier ne sont pas déclenchés avant le OnLostFocus de la popup.

    Sinon pourquoi ne pas utiliser un Menu Contextuel ?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 24
    Par défaut
    Très bonne question

    J'avais un ContextMenu à la base (avec mes ToggleButton en guise d'item). Le soucis dans ce cas c'est la présentation qui me plaisait pas pour 2 raisons :
    -> j'ai toujours l'effet de survol sur les items avec la surbrillance en bleu (par défaut).
    -> j'avais des margin de 20 autour des ToggleButton en horizontal.

    Je me doute qu'il doit être plus facile que régler des soucis de présentation que des soucis d'Event.
    L'un comme l'autre je sèche un peu :/

    EDIT:
    Je viens de ré-essayer avec un ContextMenu, il y a également un 3e soucis :
    comment faire pour que le clic sur le ToggleButton fasse également disparaitre le ContextMenu ?

    EDIT2:
    C'est bon, j'ai pu régler les 2 premiers soucis de présentation en tapant dans le ControlTemplate des MenuItem (j'avais déjà essayer mais pas au bon endroit )
    Il me reste plus que le soucis de l'EDIT précédent à savoir que mes ToggleButton provoque une "validation" de mon ContextMenu.

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    2 210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 210
    Par défaut
    Citation Envoyé par sephirostoy
    Il me reste plus que le soucis de l'EDIT précédent à savoir que mes ToggleButton provoque une "validation" de mon ContextMenu.
    Tu as essayé de passer la propriété IsOpen du Menu contextuel à false dans le clic du ToggleButton :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    CtMenu.IsOpen = false;

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 24
    Par défaut
    Techniquement c'est effectivement ce que je voudrais faire. Mais la question est quand ?

    Je vais peut être reclarifier la situation, voilà grossièrement à quoi ressemble ma structure XAML (les 2 objets commençant par "DT" sont mes objets personnalisé qui héritent tous les 2 de ToggleButton) :

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <DTDropDownButton>
        <ContextMenu>
            <DTToggleButton />
        </ContextMenu>
    </DTDropDownButton>

    Sachant que l'ouverture et la fermeture du ContextMenu peut être géré dans le code de DTDropDownButton.
    Mon but c'est qu'à l'appui de DTToggleButton, celui-ci fait son action de ToggleButton normal, puis notifie DTDropDownButton qu'il puisse fermer le ContextMenu.

    Le hic, c'est que j'ai pas de relation direct entre DTDropDownButton et DTToggleButton vu que ces derniers sont placés dans le ContextMenu via un ControlTemplate pour remplacer les MenuItem par mes DTToggleButton.

    Je viens de penser à une solution qui me paraissait alléchante sur le papier : utliser le mécanisme des RoutedEvent de type Bubble. Du genre :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class DTToggleButton {
        protected override void OnClick()
        {
            base.OnClick();
            RaiseEvent(new RoutedEventArgs(SizeChangedEvent, this));
        }
    }

    et

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class DTDropDownButton
    {
        public DTDropDownButton()
        {
            this.Checked += new RoutedEventHandler(DropDownButton_Checked);
        }
     
        void DropDownButton_Checked(object sender, RoutedEventArgs e)
        {
            if (sender is DTToggleButton)
            {
                IsChecked = false; // Command la fermeture du ContextMenu
            }
        }
    }

    Pour une raison que j'ignore l'event ne remonte jamais jusqu'à l'objet DTDropDownButton. Dans le doute, j'ai créé un RoutedEvent personnalisé (connu uniquement par mes 2 ToggleButton) pour éviter les conflits avec l'event Checked des 2 ToggleButton. Même résultat.
    Est-ce que ça peut venir du ContextMenu qui est intercallé entre mes 2 types de ToggleButton qui n'a pas connaissance de l'existance de mon RoutedEvent personnalisé et donc ne route pas l'event au niveau d'au-dessus ?

    Je pense qu'il faut que je revois d'avantage la structure et la hiérarchie de mes classes pour qu'il y ait un "vrai" lien entre mes 2 classes; alors que là mon DTDropDownButton n'a pas connaissance de mes DTToggleButton du niveau d'en dessous.

  6. #6
    Membre émérite Avatar de jmix90
    Homme Profil pro
    Consultant .Net
    Inscrit en
    Juillet 2007
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Consultant .Net
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2007
    Messages : 576
    Par défaut
    Coucou,

    Une idée comme ça: regarder comment est fait le template de la combobox qui a plus ou moins la même fonctionnalité que ce que tu veux et le réutiliser...

    Bon courage,

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 24
    Par défaut
    La ComboBox a le même effet : si on place un ToggleButton à l'intérieur, celui-ci ne provoque pas la fermeture de la popup quand on clique dessus.

    Finalement, j'ai rusé un peu.
    En réalité il existe bien une relation entre mes 2 types de ToggleButton.
    J'ai une architecture MVVM du type :
    - CategoryViewModel => DataContext de DTDropDownButton
    |-> SubCategoryViewModel => DataContext de DTToggleButton

    Quand je clique sur un DTToggleButton, ça me remontte un event dans CategoryViewModel comme quoi la sous catégorie à changer et cet event est redispatché vers d'autres objets externes.

    Du coup, j'en ai profité pour que ma vue (DTDropDownButton) écoute cet event et ferme la popup.

    C'est un peu con de devoir passer par le ViewModel pour des questions purement présentation, mais dans l'immédiat ça colmatte mon problème.

    Par contre, je me pose une question : comment fait-on pour créer un composant qui permet de contenir d'autres composants personnalisés ?
    Et qui puisse être utilisé comme pour les Menu / MenuItem du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <DTDropDownButton>
        <DTToggleButton Header="...">
        <DTToggleButton Header="...">
        <DTToggleButton Header="...">
    </DTDropDownButton>
    Je vois bien comment on fait pour un composant qui n'a pas de fils ou bien qui contient un fils d'un type déjà connu comme Popup ou ContextMenu, en revanche pour recréer un conteneur personnalisé, je vois pas trop.
    Si vous avez des liens vers des tuto de ce genre, je suis preneur.

    Merci d'avance.

Discussions similaires

  1. [C#] Detecter la perte de focus
    Par iowa dans le forum Windows Forms
    Réponses: 10
    Dernier message: 15/03/2006, 14h03
  2. Réponses: 9
    Dernier message: 02/02/2006, 15h46
  3. Comment détecter la perte de focus d'une fenêtre
    Par Leviathan_72 dans le forum Windows
    Réponses: 5
    Dernier message: 31/12/2005, 00h22
  4. excel -> test lors de la perte du focus d'une cellule
    Par greg778 dans le forum Macros et VBA Excel
    Réponses: 24
    Dernier message: 26/09/2005, 17h26
  5. [VB.NET] Perte de focus entre deux form
    Par toniolol dans le forum Windows Forms
    Réponses: 2
    Dernier message: 05/07/2005, 08h00

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