首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当ViewingMode设置为Scroll时,调整FlowDocumentReader的滚动增量?

当ViewingMode设置为Scroll时,调整FlowDocumentReader的滚动增量?
EN

Stack Overflow用户
提问于 2009-05-18 10:02:58
回答 3查看 13.7K关注 0票数 6

我在FlowDocumentReader中显示一个带有ViewingMode=“滚动”的ViewingMode=。如果我在鼠标上使用轮子,文档滚动的速度会非常慢。我想增加滚动步长。

  1. 我试图在控制面板中更改鼠标的滚动设置,但这没有任何效果。我认为WPF忽略了FlowDocumentScrollViewer.
  2. I've的设置在FlowDocument和FlowDocumentReader上添加了一个滚动事件,但是当我使用鼠标轮时不会触发。
  3. --我在FlowDocumentReader上添加了一个加载的事件,得到了ScrollViewer后代,从滚动查看器的模板中找到了ScrollBar ("PART_VerticalScrollBar"),并调整了SmallChange & LargeChange属性。这也没有任何效果。

有人有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-06-10 03:01:11

我们可以在一个控件的MouseWheel事件中修改它,比如Sohnee,但是它只需要针对一个特定的情况就可以解决,而且您必须能够访问FlowDocumentReader,如果您使用类似于MVVM的东西,您将无法访问它。相反,我们可以创建一个附加属性,然后可以用ScrollViewer对任何元素进行设置。在定义附加属性时,我们还需要一个PropertyChanged回调,其中我们将执行对滚动速度的实际修改。我还将我的属性默认为1,我将使用的速度范围是.1x到3倍,尽管您可以轻松地执行类似于1-10的操作。

代码语言:javascript
复制
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、ScrollViewer等等,所以我们可以做一个简短的方法,使用VisualTreeHelper来完成这个任务。我们已经知道通过的项目将是某种形式的DependancyObject,所以如果存在,我们可以使用一些递归来查找ScrollViewer。

代码语言:javascript
复制
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。一旦我们有了这两件事,我们就可以获得和修改ScrollViewer的VerticalOffset。我发现,将MouseWheelEventArgs.Delta除以鼠标轮改变的数量,6得到了大约默认的滚动速度。所以,如果我们用我们的ScrollSpeed修饰符乘以它,我们就可以得到新的偏移值。然后,我们可以使用它公开的VerticalOffset方法来设置ScrollViewer的ScrollToVerticalOffset。

代码语言:javascript
复制
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将如何在多个控件之间受到影响。

代码语言:javascript
复制
<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>

现在,当我们运行时,我们可以使用Sliders来修改每个列的滚动速度,有趣的东西。

票数 21
EN

Stack Overflow用户

发布于 2018-04-24 14:46:00

哇。Rmoore的回答很精彩,但有点复杂。我把它简化了一点。对于那些不使用MVVM或可以将代码放在可以访问目标元素的类中的人来说,这两个方法对您来说就足够了:

将此方法放置到扩展中:

代码语言:javascript
复制
   public static DependencyObject GetScrollViewer(this 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;
        }

然后将第二个方法放置到访问目标UI元素的类中,并将其订阅到"PreviewMouseWheel“事件。

代码语言:javascript
复制
     private void HandleScrollSpeed(object sender, MouseWheelEventArgs e)
        {
            try
            {
                if (!(sender is DependencyObject))
                    return;

                ScrollViewer scrollViewer = (((DependencyObject)sender)).GetScrollViewer() as ScrollViewer;
                ListBox lbHost = sender as ListBox; //Or whatever your UI element is

                if (scrollViewer != null && lbHost != null)
                {
                    double scrollSpeed = 1;
    //you may check here your own conditions
                    if (lbHost.Name == "SourceListBox" || lbHost.Name == "TargetListBox")
                        scrollSpeed = 2;

                    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.");
            }
            catch (Exception ex)
            {
//Do something...
            }
        }
票数 2
EN

Stack Overflow用户

发布于 2009-06-09 10:53:23

不要使用滚动事件,而是捕获MouseWheel事件。

代码语言:javascript
复制
<FlowDocumentReader MouseWheel="...">
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/876994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档