Question

Est-il possible de modifier le montant défilant dans le ScrollViewer WPF? Je me demande simplement s’il est possible de changer le visionneur de défilement de sorte que lors de l’utilisation de la molette de la souris ou des flèches du visionneur de défilement, la quantité de défilement incrémentiel puisse être modifiée.

Était-ce utile?

La solution

La réponse courte est: il n’est pas possible de faire cela sans écrire du code de défilement personnalisé, mais ne vous laissez pas effrayer, ce n’est pas si difficile.

ScrollViewer fonctionne en faisant défiler en utilisant des unités physiques (pixels) ou en s’engageant dans une implémentation IScrollInfo pour utiliser des unités logiques. Ceci est contrôlé par le paramètre de la propriété CanContentScroll où la valeur false signifie "faire défiler le contenu en utilisant des unités physiques" et une valeur de true signifie "faire défiler le contenu de manière logique".

Alors, comment ScrollViewer fait-il défiler le contenu logiquement? En communiquant avec une implémentation IScrollInfo. C'est ainsi que vous pouvez déterminer exactement le défilement du contenu de votre panneau lorsqu'une personne exécute une action logique. Consultez la documentation relative à IScrollInfo pour obtenir une liste de toutes les unités de mesure logiques qu'il est possible de demander de faire défiler, mais puisque vous avez mentionné la molette de la souris, les méthodes MouseWheel Up / Down / Left / Right vous intéresseront surtout.

Autres conseils

Voici une classe WPF ScrollViewer simple, complète et qui a une propriété SpeedFactor pouvant être liée à des données pour régler la sensibilité de la molette de la souris. Définir SpeedFactor sur 1.0 signifie un comportement identique à celui de WPF ScrollViewer . La valeur par défaut de la propriété de dépendance est 2.5 , ce qui permet un défilement très rapide.

Bien sûr, vous pouvez également créer des fonctionnalités supplémentaires utiles en liant la propriété SpeedFactor , c'est-à-dire, pour permettre à l'utilisateur de contrôler facilement le multiplicateur.

public class WheelSpeedScrollViewer : ScrollViewer
{
    public static readonly DependencyProperty SpeedFactorProperty =
        DependencyProperty.Register(nameof(SpeedFactor),
                                    typeof(Double),
                                    typeof(WheelSpeedScrollViewer),
                                    new PropertyMetadata(2.5));

    public Double SpeedFactor
    {
        get { return (Double)GetValue(SpeedFactorProperty); }
        set { SetValue(SpeedFactorProperty, value); }
    }

    protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
    {
        if (!e.Handled && 
            ScrollInfo is ScrollContentPresenter scp &&
            ComputedVerticalScrollBarVisibility == Visibility.Visible)
        {
            scp.SetVerticalOffset(VerticalOffset - e.Delta * SpeedFactor);
            e.Handled = true;
        }
    }
};

Démonstration XAML complète du 'défilement rapide de la souris' d'environ 3200 données:

<UserControl x:Class="RemoveDuplicateTextLines.FastScrollDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyApp"
    xmlns:sys="clr-namespace:System;assembly=mscorlib">

    <local:WheelSpeedScrollViewer VerticalScrollBarVisibility="Auto">
        <ListBox ItemsSource="{Binding Source={x:Type sys:Object},Path=Assembly.DefinedTypes}" />
    </local:WheelSpeedScrollViewer>

</UserControl>

Molette de la souris rapide:

 entrer la description de l'image ici

Vous pouvez implémenter un comportement sur le scrollviewer. Dans mon cas, CanContentScroll ne fonctionnait pas. La solution ci-dessous permet de faire défiler la souris avec la molette de la souris et de déplacer la barre de défilement.

public class StepSizeBehavior : Behavior<ScrollViewer>
{
    public int StepSize { get; set; }

    #region Attach & Detach
    protected override void OnAttached()
    {
        CheckHeightModulesStepSize();
        AssociatedObject.ScrollChanged += AssociatedObject_ScrollChanged;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.ScrollChanged -= AssociatedObject_ScrollChanged;
        base.OnDetaching();
    }
    #endregion

    [Conditional("DEBUG")]
    private void CheckHeightModulesStepSize()
    {
        var height = AssociatedObject.Height;
        var remainder = height%StepSize;
        if (remainder > 0)
        {
            throw new ArgumentException(
<ScrollViewer MaxHeight="248"
              VerticalScrollBarVisibility="Auto">
    <i:Interaction.Behaviors>
        <behaviors:StepSizeBehavior StepSize="62" />
    </i:Interaction.Behaviors>
quot;{nameof(StepSize)} should be set to a value by which the height van be divised without a remainder."); } } private void AssociatedObject_ScrollChanged(object sender, ScrollChangedEventArgs e) { const double stepSize = 62; var scrollViewer = (ScrollViewer)sender; var steps = Math.Round(scrollViewer.VerticalOffset / stepSize, 0); var scrollPosition = steps * stepSize; if (scrollPosition >= scrollViewer.ScrollableHeight) { scrollViewer.ScrollToBottom(); return; } scrollViewer.ScrollToVerticalOffset(scrollPosition); } }

Vous l'utiliseriez comme ceci:

<*>

Je l'ai fait pour garantir des nombres entiers sur la barre de défilement1.ValueChanged:

scrollbar1.Value = Math.Round(scrollbar1.Value, 0, MidpointRounding.AwayFromZero)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top