当 ViewingMode 设置为滚动时,调整 FlowDocumentReader 的滚动增量? [英] Adjust FlowDocumentReader's Scroll Increment When ViewingMode Set to Scroll?

查看:20
本文介绍了当 ViewingMode 设置为滚动时,调整 FlowDocumentReader 的滚动增量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ViewingMode="Scroll" 在 FlowDocumentReader 中显示 FlowDocument.如果我使用鼠标上的滚轮,文档滚动得非常缓慢.我想增加滚动步骤.

I'm displaying a FlowDocument in a FlowDocumentReader with the ViewingMode="Scroll". If I use the wheel on my mouse, the document scrolls very slowly. I'd like to increase the scroll step.

  1. 我尝试在控制面板中更改鼠标的滚动设置,但这没有任何效果.我认为 WPF 会忽略 FlowDocumentScrollViewer 的该设置.

  1. I've tried to change the Scroll setting of my mouse in Control Panel, but that doesn't have any effect. I think that WPF ignores that setting for the FlowDocumentScrollViewer.

我在 FlowDocument 和 FlowDocumentReader 上添加了一个 Scroll 事件,但是当我使用鼠标滚轮时它不会触发.

I've added a Scroll event on the FlowDocument and FlowDocumentReader, but that doesn't fire when I use the mouse wheel.

我在 FlowDocumentReader 上添加了一个 Loaded 事件,得到了 ScrollViewer 的后代,从滚动查看器的模板中找到了 ScrollBar ("PART_VerticalScrollBar") 并调整了 SmallChange &LargeChange 属性.这也没有任何影响.

I've added a Loaded event on the FlowDocumentReader, got the ScrollViewer descendant, found the ScrollBar ("PART_VerticalScrollBar") from the scroll viewer's template and adjusted the SmallChange & LargeChange properties. That also didn't have any effect.

有人有什么想法吗?

推荐答案

我们可以在 Control 的 MouseWheel 事件中修改它,比如 Sohnee sugested,但是它只能针对一个特定情况解决,而你必须可以访问 FlowDocumentReader,如果您使用 MVVM 之类的东西,则不会.相反,我们可以创建一个附加属性,然后我们可以使用 ScrollViewer 在任何元素上设置该属性.在定义我们的附加属性时,我们还需要一个 PropertyChanged 回调,我们将在其中对滚动速度执行实际修改.我还给我的属性一个默认值 1,我要使用的速度范围是 0.1x 到 3x,尽管你可以很容易地做类似 1-10 的事情.

We can modify this in a Control's MouseWheel event, like Sohnee sugested, but then it'd just be solved for one specific case, and you'd have to have access to the FlowDocumentReader, which if your usinging something like MVVM, you wont. Instead, we can create an attached property that we can then set on any element with a ScrollViewer. When defining our attached property, we also are going to want a PropertyChanged callback where we will perform the actual modifications to the scroll speed. I also gave my property a default of 1, the range of speed I'm going to use is .1x to 3x, though you could just as easily do something like 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 事件之前发生.

Now that we have our Attached Property we need to handle the scrolling, to do this, in the OnScrollSpeedChanged we can handle the PreviewMouseWheel event. We want to hook into the PreviewMouseWheel, since it is a tunneling event that will occur before the ScrollViewer can handle the standard MouseWheel event.

目前,PreviewMouseWheel 处理程序接收 FlowDocumentReader 或我们绑定到的其他东西,但是我们需要的是 ScrollViewer.由于它可能有很多东西:ListBox、FlowDocumentReader、WPF Toolkit Grid、ScrollViewer 等,我们可以制作一个使用 VisualTreeHelper 来执行此操作的简短方法.我们已经知道通过的项将是某种形式的 DependancyObject,因此我们可以使用一些递归来查找 ScrollViewer(如果它存在).

Currently, the PreviewMouseWheel handler is taking in the FlowDocumentReader or other thing that we bound it to, however what we need is the ScrollViewer. Since it could be a lot of things: ListBox, FlowDocumentReader, WPF Toolkit Grid, ScrollViewer, etc, we can make a short method that uses the VisualTreeHelper to do this. We already know that the item coming through will be some form of DependancyObject, so we can use some recursion to find the ScrollViewer if it exists.

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 修饰符,我们就可以得到新的偏移值.然后我们可以使用它公开的 ScrollToVerticalOffset 方法设置 ScrollViewer 的 VerticalOffset.

Now that we can get the ScrollViwer we can finally modify the scroll speed. We'll need to get the ScrollSpeed property from the DependancyObject that is being sent through. Also, we can use our helper method to get the ScrollViewer that is contained within the element. Once we have these two things, we can get and modify the ScrollViewer's VerticalOffset. I found that dividing the MouseWheelEventArgs.Delta, which is the amount that the mouse wheel changed, by 6 gets approximately the default scroll speed. So, if we multiply that by our ScrollSpeed modifier, we can then get the new offset value. We can then set the ScrollViewer's VerticalOffset using the ScrollToVerticalOffset method that it exposes.

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 将如何在多个控件之间受到影响.

Now that we've got our Attached Property set up, we can create a simple UI to demonstrate it. I'm going to create a ListBox, and a FlowDocumentReaders so that we can see how the ScrollSpeed will be affected across multiple controls.

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

现在,当运行时,我们可以使用滑块来修改每一列的滚动速度,有趣的东西.

Now, when run, we can use the Sliders to modify the scrolling speed in each of the columns, fun stuff.

这篇关于当 ViewingMode 设置为滚动时,调整 FlowDocumentReader 的滚动增量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆