Можно ли изменить количество прокрутки прокрутки WPF ScrollViewer? Я просто задаюсь вопросом, можно ли изменить scrollviewer так, чтобы при использовании колеса мыши или стрелок scrollviewer количество инкрементной прокрутки можно было изменить.
Количество прокрутки ScrollViewer Wpf
Ответ 1
Короткий ответ: нет никакого способа сделать это, не написав какой-то пользовательский прокручиваемый код, но не позволяйте этому напугать вас не так уж сложно.
ScrollViewer либо работает путем прокрутки с использованием физических единиц (то есть пикселей), либо путем взаимодействия с реализацией IScrollInfo для использования логических единиц. Это контролируется параметром свойство CanContentScroll, где значение false означает "прокрутка содержимого с использованием физических единиц", а значение true означает "прокрутка" контент логически ".
Итак, как ScrollViewer логически прокручивает контент? Обмениваясь информацией с реализацией IScrollInfo. Так, чтобы вы могли точно определить, сколько содержимого вашей панели прокручивается, когда кто-то выполняет логическое действие. Взгляните на документацию для IScrollInfo, чтобы получить список всех логических единиц измерения, которые могут запрашиваться для прокрутки, но так как вы упомянули мы будем в основном интересоваться методами MouseWheelUp/Down/Left/Right.
Ответ 2
Вот простой, полный и рабочий класс 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 элементов данных:
примечание: ссылка на mscorlib предназначена только для доступа к демонстрационным данным.
<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>
Быстрое колесо мыши:
Ответ 3
Вы можете реализовать поведение в scrollviewer. В моем случае 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($"{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);
}
}
Вы бы использовали его следующим образом:
<ScrollViewer MaxHeight="248"
VerticalScrollBarVisibility="Auto">
<i:Interaction.Behaviors>
<behaviors:StepSizeBehavior StepSize="62" />
</i:Interaction.Behaviors>
Ответ 4
Я сделал это, чтобы обеспечить целые числа на scrollbar1.ValueChanged:
scrollbar1.Value = Math.Round(scrollbar1.Value, 0, MidpointRounding.AwayFromZero)