Мы можем изменить это в случае MouseWheel элемента управления, как Sohnee мотивационные, но тогда это было бы просто решить для одного конкретного случая, и вы должны иметь доступ к FlowDocumentReader, что если ваш usinging что-то вроде MVVM, вы не будете. Вместо этого мы можем создать прикрепленное свойство, которое затем можно установить на любой элемент с ScrollViewer. При определении нашего прикрепленного свойства нам также понадобится обратный вызов PropertyChanged, где мы будем выполнять фактические изменения скорости прокрутки. Я также дал моему свойству значение по умолчанию 1, диапазон скорости, который я собираюсь использовать, составляет от .1x до 3x, хотя вы можете так же легко сделать что-то вроде 1-10.
public static double GetScrollSpeed(DependencyObject obj)
{
return (double)obj.GetValue(ScrollSpeedProperty);
}
public static void SetScrollSpeed(DependencyObject obj, double value)
{
obj.SetValue(ScrollSpeedProperty, value);
}
public static readonly DependencyProperty ScrollSpeedProperty =
DependencyProperty.RegisterAttached(
"ScrollSpeed",
typeof(double),
typeof(ScrollHelper),
new FrameworkPropertyMetadata(
1.0,
FrameworkPropertyMetadataOptions.Inherits & FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnScrollSpeedChanged)));
private static void OnScrollSpeedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
}
Теперь, когда у нас есть вложенное свойство, мы должны обращаться с прокруткой, чтобы сделать это, в OnScrollSpeedChanged мы можем обрабатывать событие PreviewMouseWheel. Мы хотим подключиться к PreviewMouseWheel, поскольку это событие туннелирования, которое произойдет до того, как ScrollViewer сможет обрабатывать стандартное событие MouseWheel.
В настоящее время обработчик PreviewMouseWheel принимает в FlowDocumentReader или другую вещь, к которой мы привязали ее, однако нам нужен ScrollViewer. Поскольку это может быть много: ListBox, FlowDocumentReader, WPF Toolkit Grid, ScrollViewer и т. Д., Мы можем сделать короткий метод, который использует VisualTreeHelper для этого. Мы уже знаем, что элемент, проходящий через него, будет какой-то формой DependancyObject, поэтому мы можем использовать некоторую рекурсию, чтобы найти ScrollViewer, если она существует.
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;
}
private static void OnScrollSpeedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var host = o as UIElement;
host.PreviewMouseWheel += new MouseWheelEventHandler(OnPreviewMouseWheelScrolled);
}
Теперь, когда мы можем получить ScrollViwer, мы можем, наконец, изменить скорость прокрутки. Нам нужно получить свойство ScrollSpeed из объекта DependancyObject, который отправляется через. Кроме того, мы можем использовать наш вспомогательный метод, чтобы получить ScrollViewer, который содержится внутри элемента. Как только у нас есть эти две вещи, мы можем получить и изменить VerticalOffset ScrollViewer. Я обнаружил, что разделение MouseWheelEventArgs.Delta, которое является величиной, которую изменило колесо мыши, на 6 получает приблизительно скорость прокрутки по умолчанию. Итак, если мы умножим это на наш модификатор ScrollSpeed, мы можем получить новое значение смещения. Затем мы можем установить VerticalOffset ScrollViewer с помощью метода ScrollToVerticalOffset, который он предоставляет.
private static void OnPreviewMouseWheelScrolled(object sender, MouseWheelEventArgs e)
{
DependencyObject scrollHost = sender as DependencyObject;
double scrollSpeed = (double)(scrollHost).GetValue(Demo.ScrollSpeedProperty);
ScrollViewer scrollViewer = GetScrollViewer(scrollHost) as ScrollViewer;
if (scrollViewer != null)
{
double offset = scrollViewer.VerticalOffset - (e.Delta * scrollSpeed/6);
if (offset < 0)
{
scrollViewer.ScrollToVerticalOffset(0);
}
else if (offset > scrollViewer.ExtentHeight)
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.ExtentHeight);
}
else
{
scrollViewer.ScrollToVerticalOffset(offset);
}
e.Handled = true;
}
else
{
throw new NotSupportedException("ScrollSpeed Attached Property is not attached to an element containing a ScrollViewer.");
}
}
Теперь, когда у нас установлено наше прикрепленное свойство, мы можем создать простой пользовательский интерфейс, чтобы продемонстрировать его. Я собираюсь создать ListBox и FlowDocumentReaders, чтобы мы могли видеть, как ScrollSpeed будет затронуто несколькими элементами управления.
<UniformGrid Columns="2">
<DockPanel>
<Slider DockPanel.Dock="Top"
Minimum=".1"
Maximum="3"
SmallChange=".1"
Value="{Binding ElementName=uiListBox, Path=(ScrollHelper:Demo.ScrollSpeed)}" />
<ListBox x:Name="uiListBox">
<!-- Items -->
</ListBox>
</DockPanel>
<DockPanel>
<Slider DockPanel.Dock="Top"
Minimum=".1"
Maximum="3"
SmallChange=".1"
Value="{Binding ElementName=uiListBox, Path=(ScrollHelper:Demo.ScrollSpeed)}" />
<FlowDocumentReader x:Name="uiReader"
ViewingMode="Scroll">
<!-- Flow Document Content -->
</FlowDocumentReader>
</DockPanel>
</UniformGrid>
Теперь при запуске мы можем использовать ползунки для изменения скорости прокрутки в каждом столбце, забавного материала.
Если твинг, который вы должны были выполнить в ответ, был с «/ 6» для стандартной скорости, я понял лучший способ сделать это, отвечая на другой вопрос. Если вы вместо этого умножаете SystemInformation.MouseWheelScrollLines/3 (текущие настройки компьютера/по умолчанию), то он должен работать на основе пользовательских настроек мыши вместо статической скорости. – rmoore