Empêcher le défilement lorsque la souris entre dans la liste déroulante WPF ComboBox

Quand un ComboBox a un grand nombre d'éléments, sa liste déroulante devient défilante. Lorsque l'utilisateur appelle cette liste déroulante et déplace le curseur de la souris pour entrer les limites de la liste déroulante à partir du bas, la liste déroulante fait défiler immédiatement un ou plusieurs éléments dans la liste (de goobering: se produit également lors de la sortie des limites via le bord inférieur).

Ce défilement n'est pas intuitif, car la liste ne défile pas vers le haut lors de la saisie des limites par le haut.

Comment pouvons-nous désactiver le comportement de défilement automatique?

Dans Visual Studio, ce comportement peut être observé via la liste déroulante membre de la barre de navigation de l'éditeur de code (CTRL+F2 ).

25
demandé sur Bhargav Rao 2015-04-15 01:01:46

3 réponses

Une façon de résoudre ce problème est d'utiliser un comportement (ou plutôt une propriété attachée de type comportement) pour s'abonner à l'événement RequestBringIntoView du ComboBoxItems, puis définir le RequestBringIntoViewEventArgs.Handled sur true. Cela peut également être fait à petite échelle en utilisant un EventSetter et codebehind.

 <Style TargetType="ComboBoxItem">                    
     <EventSetter Event="RequestBringIntoView" Handler="OnRequestBringIntoView"/>
 </Style>

private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
    //Allows the keyboard to bring the items into view as expected:
    if (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up))
        return;            

    e.Handled = true;            
}

Modifier

J'ai trouvé que vous pouvez obtenir le même effet en manipulant L'événement RequestBringIntoView sur le ItemsPanel plutôt que les éléments eux-mêmes. Mais même résultat:

<ComboBox.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel RequestBringIntoView="OnRequestBringIntoView"/>
    </ItemsPanelTemplate>
</ComboBox.ItemsPanel>
14
répondu Andrew Hanlon 2015-04-23 23:00:03

D'après ce que je peux dire, cela semble être causé par les éléments au bas de la lumière étant "partiellement affichés", où un élément est tronqué par le conteneur. Lorsque la souris passe sur un élément partiel comme celui-ci, WPF fait défiler l'élément entier en vue, ce qui peut parfois laisser un autre élément partiel en bas.

Dans Winforms, cela peut être corrigé en définissant .IntegralHeight, mais aucune propriété de ce type n'existe dans WPF d'après ce que je peux dire. Si tous les éléments de votre combobox ont la même hauteur vous pourrait lier la hauteur de la liste de la liste déroulante à un multiple de la hauteur de l'élément, par exemple, afficher 10 x 20px éléments de hauteur, réglez-le à 200.

5
répondu Bradley Uffner 2015-04-17 16:31:56

La réponse sélectionnée D'Andrew Hanlon évite que la liste défile jusqu'à l'élément sélectionné lorsqu'elle est ouverte. J'ai aussi dû ajouter ceci dans le gestionnaire d'événements ("list" est la liste déroulante):

private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
    //Allows the keyboard to bring the items into view as expected:
    if (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up))
        return;

    // Allows to bring the selected item into view:
    if (((ComboBoxItem)e.TargetObject).Content == list.SelectedItem)
        return;

    e.Handled = true;
}
1
répondu dada 2018-01-16 12:40:07