我們可以在控制的鼠標滾輪事件修改此,像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事件。我們希望鉤入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,我們可以最終修改滾動速度。我們需要從正在發送的DependancyObject中獲取ScrollSpeed屬性。另外,我們可以使用我們的helper方法來獲取元素中包含的ScrollViewer。一旦我們有了這兩件事,我們就可以獲得並修改ScrollViewer的VerticalOffset。我發現將MouseWheelEventArgs.Delta(鼠標滾輪改變的量)除以6得到大約默認的滾動速度。所以,如果我們用ScrollSpeed修飾符乘以那個,我們就可以得到新的偏移值。然後,我們可以使用它公開的ScrollToVerticalOffset方法來設置ScrollViewer的VerticalOffset。
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來演示它。我將創建一個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>
現在,運行時,我們可以使用滑塊來修改每列中的滾動速度,有趣的東西。
如果你對我的回答所要做的tweeking與標準速度的'/ 6'一樣,我在回答另一個問題時意識到了一個更好的方法。如果您乘以SystemInformation.MouseWheelScrollLines/3(當前計算機設置/默認值),則它應該基於用戶鼠標設置而不是靜態速度工作。 – rmoore 2009-06-10 23:29:07