web-dev-qa-db-fra.com

Est-il possible d'implémenter le défilement régulier dans une listview WPF?

Est-il possible d'implémenter le défilement régulier dans une variable WPF listview comme son fonctionnement dans Firefox?
Lorsque le navigateur Firefox contient tous les éléments listview et que vous maintenez le bouton central de la souris enfoncé (sans le relâcher) et que vous le faites glisser, les éléments listview doivent défiler en douceur. Lorsque vous relâchez, cela devrait cesser.

Il semble que ce ne soit pas possible dans les winforms, mais je me demande s'il est disponible dans WPF?

37
Joan Venge

Vous pouvez obtenir un défilement régulier, mais vous perdez la virtualisation des éléments. Vous devez donc utiliser cette technique uniquement si la liste contient quelques éléments:

Infos ici: Défilement en douceur dans la liste

Avez-vous essayé de régler:

ScrollViewer.CanContentScroll="False"

sur la liste?

De cette façon, le défilement est géré par le panneau plutôt que par le listBox ... Vous perdez la virtualisation si vous le faites bien, ce qui risque de ralentir si vous avez beaucoup de contenu.

65
Pop Catalin

Il est en effet possible de faire ce que vous demandez, mais cela nécessitera une bonne quantité de code personnalisé. 

Normalement, dans WPF, ScrollViewer utilise ce que l’on appelle le défilement logique, c’est-à-dire qu’il fait défiler élément par élément au lieu d’une valeur de décalage. Les autres réponses couvrent certaines des manières dont vous pouvez changer le comportement de défilement logique en comportement de défilement physique. L'autre méthode consiste à utiliser les méthodes ScrollToVertialOffset et ScrollToHorizontalOffset exposées à la fois par ScrollViwer et IScrollInfo. 

Pour implémenter la plus grande partie, le défilement lorsque la molette de la souris est enfoncée, nous devrons utiliser les événements MouseDown et MouseMove.

<ListView x:Name="uiListView"
          Mouse.MouseDown="OnListViewMouseDown"
          Mouse.MouseMove="OnListViewMouseMove"
          ScrollViewer.CanContentScroll="False">
    ....
</ListView>

Dans MouseDown, nous allons enregistrer la position actuelle de la souris, que nous utiliserons comme point relatif pour déterminer la direction dans laquelle nous défilons. Dans le déplacement de la souris, nous allons obtenir le composant ScrollViwer de ListView puis le faire défiler en conséquence.

private Point myMousePlacementPoint;

private void OnListViewMouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.MiddleButton == MouseButtonState.Pressed)
    {
        myMousePlacementPoint = this.PointToScreen(Mouse.GetPosition(this));
    }
}

private void OnListViewMouseMove(object sender, MouseEventArgs e)
{
    ScrollViewer scrollViewer = ScrollHelper.GetScrollViewer(uiListView) as ScrollViewer;

    if (e.MiddleButton == MouseButtonState.Pressed)
    {
        var currentPoint = this.PointToScreen(Mouse.GetPosition(this));

        if (currentPoint.Y < myMousePlacementPoint.Y)
        {
            scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - 3);
        }
        else if (currentPoint.Y > myMousePlacementPoint.Y)
        {
            scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + 3);
        }

        if (currentPoint.X < myMousePlacementPoint.X)
        {
            scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 3);
        }
        else if (currentPoint.X > myMousePlacementPoint.X)
        {
            scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + 3);
        }
    }
}

public static DependencyObject GetScrollViewer(DependencyObject o)
{
    // Return the DependencyObject if it is a ScrollViewer
    if (o is ScrollViewer)
    { return o; }

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
    {
        var child = VisualTreeHelper.GetChild(o, i);

        var result = GetScrollViewer(child);
        if (result == null)
        {
            continue;
        }
        else
        {
            return result;
        }
    }
    return null;
}

Il y a certains domaines qui manquent car il ne s'agit que d'une validation de principe, mais cela devrait certainement vous permettre de démarrer dans la bonne direction. Pour le faire défiler constamment une fois que la souris est éloignée du point MouseDown initial, la logique de défilement peut aller dans DispatcherTimer ou quelque chose de similaire.

10
rmoore

Si vous utilisez .NET 4.5 (ou 4.0 si vous êtes prêt à pirater un peu), alors il y a une réponse par ici .

3
Zodman

Essayez de définir la propriété ScrollViewer.CanContentScroll Attache sur false sur le ListView . Mais comme Pop Catalin dit, vous perdez la virtualisation des éléments, ce qui signifie que tous les éléments de la liste sont chargés et remplis en même temps, et non lorsqu'un ensemble d'éléments doit être affiché. Par conséquent, si la liste est volumineuse, causer des problèmes de mémoire et de performances.

3
Eddie

essayez de définir la hauteur de la vue liste comme automatique et de l'envelopper dans une visionneuse à défilement.

<ScrollViewer IsTabStop="True" VerticalScrollBarVisibility="Auto">
     <ListView></ListView>
</ScrollViewer>

N'oubliez pas de mentionner la hauteur de ScrollViewer J'espère que cela vous aidera ....

0
Nitron