Вопрос

Можно ли изменить сумму, которую прокручивает WPF ScrollViewer? Мне просто интересно, можно ли изменить прокручиватель, чтобы при использовании колесика мыши или стрелок прокрутки можно было изменять величину добавочной прокрутки.

Это было полезно?

Решение

Короткий ответ: нет способа сделать это без написания какого-то пользовательского кода прокрутки, но пусть это не пугает вас, это не так уж сложно.

ScrollViewer работает либо путем прокрутки с использованием физических единиц (то есть пикселей), либо с помощью реализации IScrollInfo для использования логических единиц. Это контролируется настройкой свойства CanContentScroll где значение false означает «прокрутить содержимое с использованием физических единиц»; и значение true означает «прокручивать содержимое логически».

Так как же ScrollViewer прокручивает содержимое логически? Общаясь с реализацией IScrollInfo. Таким образом, вы можете точно определить, сколько контента на вашей панели прокручивается, когда кто-то выполняет логическое действие. Ознакомьтесь с документацией для IScrollInfo получить список всех логических единиц измерения, которые можно запросить для прокрутки, но поскольку вы упомянули колесо мыши, вас больше всего заинтересуют методы MouseWheelUp / Down / Left / Right.

Другие советы

Вот простой, полный и работающий класс WPF ScrollViewer , который имеет привязываемое к данным свойство SpeedFactor для настройки чувствительности колеса мыши. Установка для SpeedFactor значения 1.0 означает поведение, идентичное поведению WPF ScrollViewer . Значение по умолчанию для свойства зависимости 2,5 , что обеспечивает очень быструю прокрутку колес.

Конечно, вы также можете создавать дополнительные полезные функции, связываясь с самим свойством SpeedFactor , то есть с легкостью позволяя пользователю управлять множителем.

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;
        }
    }
};

Завершите демонстрацию XAML «быстрой прокрутки колесика мыши», включающую около 3200 элементов данных:

<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>

Быстрое колесо мыши:

 введите описание изображения здесь

Вы могли бы реализовать поведение на просмотрщике прокрутки. В моем случае CanContentScroll не работал. Приведенное ниже решение подходит для прокрутки колесиком мыши, а также для перемещения полосы прокрутки.

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); } }

Вы бы использовали это так:

<*>

Я сделал это, чтобы обеспечить целые числа на scrollbar1.ValueChanged:

scrollbar1.Value = Math.Round(scrollbar1.Value, 0, MidpointRounding.AwayFromZero)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top