Sohnee이 sugested처럼 우리는 컨트롤의 마우스 휠 이벤트에서 이것을 수정할 수 있지만 그것은 단지 하나의 특정 경우에 해결 될 것입니다, 당신은 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 이벤트를 처리 할 수 있습니다,이 작업을 수행하기 위해, 스크롤을 처리해야합니다. ScrollViewer가 표준 MouseWheel 이벤트를 처리하기 전에 발생하는 터널링 이벤트이므로 PreviewMouseWheel에 연결하려고합니다.
현재 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를 얻을 수 있으므로 스크롤 속도를 최종적으로 수정할 수 있습니다. 우리는 보내지는 DependancyObject에서 ScrollSpeed 속성을 가져와야합니다. 또한 도우미 메서드를 사용하여 요소 내에 포함 된 ScrollViewer를 가져올 수 있습니다. 이 두 가지가 생기면 ScrollViewer의 VerticalOffset을 가져 와서 수정할 수 있습니다. 마우스 휠이 변경된 MouseWheelEventArgs.Delta를 6으로 나누면 대략 기본 스크롤 속도가된다는 것을 알았습니다. 따라서 ScrollSpeed 수정자를 곱하면 새 오프셋 값을 얻을 수 있습니다. 그런 다음 ScrollViewer의 VerticalOffset을 노출하는 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.");
}
}
이제 첨부 된 속성이 설정되었으므로 간단한 UI를 만들어서 보여줍니다. ScrollSpeed가 여러 컨트롤에서 어떻게 영향을 받는지 확인할 수 있도록 ListBox 및 FlowDocumentReaders를 만듭니다.
<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>
이제 실행시 슬라이더를 사용하여 각 열의 재미있는 스크롤 속도를 수정할 수 있습니다.
내 대답에 대해 수행해야 할 tweeking이 표준 속도에 대한 '/ 6'인 경우 다른 질문에 답하면서 더 나은 방법을 실감했습니다. 대신 SystemInformation.MouseWheelScrollLines/3 (현재 컴퓨터 설정/기본값)을 곱하면 정적 속도 대신 사용자 마우스 설정에 따라 작동해야합니다. – rmoore