web-dev-qa-db-fra.com

La molette de la souris ScrollViewer ne fonctionne pas

Je travaille actuellement sur mon premier projet WPF et j'essaie de faire une liste déroulante. Au début, je pensais que cela pourrait être facilement fait en limitant simplement la largeur et la hauteur de la vue de liste et en forçant ainsi une barre de défilement à apparaître automatiquement chaque fois que le contenu dépasse son espace. Cela semblait bien au début, mais en raison de l'événement PreviewMouseDown géré (qui permet de faire glisser les éléments de la liste), cela ne fonctionne pas après avoir sélectionné un élément.

Deuxième tentative (en utilisant ScrollViewer)

<ScrollViewer>
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"
              Height="450" Width="200"/>
</ScrollViewer>

Bien sûr, cela a entraîné une deuxième barre de défilement chaque fois que le contenu de la liste est devenu plus grand que sa hauteur maximale. Et faire glisser la barre ne fonctionnait toujours pas après avoir sélectionné un élément.

Troisième (assez stupide) tentative (désactivation du double de la barre de défilement)

<ScrollViewer>
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"
              Height="450" Width="200"
              ScrollViewer.VerticalScrollBarVisibility="Disabled"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</ScrollViewer>

Cela a supprimé le double de la barre de défilement et activé le défilement via la molette de la souris, mais a désactivé la barre de défilement, vous ne pouviez donc pas vous déplacer en cliquant et en la faisant glisser.

Quatrième tentative (taille constante du ScrollViewer)

<ScrollViewer Height="450" Width="200">
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"/>
</ScrollViewer>

Suppression de la contrainte de largeur/hauteur du ListView et déplacement vers le ScrollViewer. Cela active la barre de défilement et supprime le doublon. Malheureusement, la molette de la souris ne fonctionne plus (faire glisser la barre de défilement fonctionne bien).

Quelqu'un pourrait-il m'expliquer pourquoi la molette de la souris ne fonctionne plus et comment y remédier?

Edit Peut-être que je devrais revenir à ma première solution. De toute évidence, le modèle de ListView contient déjà un ScrollViewer. Le problème restant serait alors que je ne peux pas faire glisser la barre de défilement après avoir sélectionné un élément en raison de l'événement PreviewMouseDown géré (le défilement via la molette fonctionne toujours dans ce cas). Dois-je gérer le glissement des éléments différemment (cela a bien fonctionné pour moi, avant de vouloir ajouter une barre de défilement)? Ou existe-t-il un moyen de détecter si le curseur est au-dessus de la barre de défilement (afin que je puisse ensuite désélectionner l'élément qui permet le défilement)? Ou y a-t-il d'autres suggestions?

53
sadeniju

Cela peut vous aider ..

private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
   ScrollViewer scv = (ScrollViewer)sender;
   scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
   e.Handled = true;
 }
86
Rocky

Ce serait probablement la solution la plus confortable:

        <ListView.Template>
            <ControlTemplate>
                <ScrollViewer>
                    <ItemsPresenter></ItemsPresenter>
                </ScrollViewer>
            </ControlTemplate>
        </ListView.Template>
18
Dbl
<ScrollViewer Background="Transparent">

Si Arrière-plan est nul, la molette de la souris ne fonctionnera pas sur ScrollViewer. Vous pouvez définir l'arrière-plan sur Transparent ou une autre valeur.

9
665

dans mon cas :

<ScrollViewer ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
    <DataGrid x:Name="dataGrid" SelectionMode="Single" ItemsSource="{Binding}"  SelectedValuePath="{Binding Item}" AutoGenerateColumns="True">
    </DataGrid>
</ScrollViewer>

la conception consistait à désactiver l'attribut VerticalScrollBarVisibility dans la portée externe, c'est-à-dire dans ScrollViewer

4
Maksim Rodkin

Pour moi, cela a fonctionné:

<ListView.Template>
    <ControlTemplate>
        <!-- Empty template to allow ScrollViewer to capture mouse scroll -->
        <ItemsPresenter />
    </ControlTemplate>
</ListView.Template>

au lieu de cela:

<ListView.Template>
    <ControlTemplate>
        <ScrollViewer>
            <ItemsPresenter></ItemsPresenter>
        </ScrollViewer>
    </ControlTemplate>
</ListView.Template>
4
J Pollack

Je veux ajouter quelques commentaires à la solution proposée par Rocky. Cela a bien fonctionné pour moi, mais plus tard, j'ai dû l'utiliser dans une autre fenêtre pour faire défiler la grille. J'ai rencontré un problème: le scrollviewer ne défilait pas jusqu'en bas. La raison était due à des tentatives de définition de la valeur VerticalOffset non valide. Le code ci-dessous fonctionne bien pour moi (il suffit de changer le gestionnaire PreviewMouseWheel:

private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        ScrollViewer scroll = (ScrollViewer)sender;
        if (e.Delta < 0)
        {
            if (scroll.VerticalOffset - e.Delta <= scroll.ExtentHeight - scroll.ViewportHeight)
            {
                scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
            }
            else
            {
                scroll.ScrollToBottom();
            }
        }
        else
        {
            if (scroll.VerticalOffset + e.Delta > 0)
            {
                scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
            }
            else
            {
                scroll.ScrollToTop();
            }
        }
        e.Handled = true;
    }
0
Ruzaki