WPF通过子容器滚动父容器

时间:2014-09-04 20:17:08

标签: wpf xaml scrollview

我在尝试弄清楚如何滚动包含在滚动查看器内的网格内容时遇到了一些问题。当尝试使用鼠标滚轮或平移(使用触摸屏)滚动时,如果鼠标/触摸点位于空白区域上,则网格会滚动,但如果它高于某些控件(例如组合框),则会赢得&# 39;滚动。我是否缺少某些属性以允许子面板允许它们滚动其父容器?

修改 我错误地说明了我的原始布局。这是我的senario的简化版本:

<Grid>
    <ScrollViewer Name="MainScrollViewer">
        <StackPanel>
            <ListBox />    <--Doesn't Scroll-->
            <Button />     <--Scrolls Fine-->
            <TextBlock />  <--Scrolls Fine-->
            <TextBox />    <--Scrolls Fine-->
            <DataGrid />   <--Doesn't Scroll-->
        </StackPanel>
    </ScrollViewer>
</Grid>

一位同事指出我的问题是由于ListBoxes和DataGrids等控件本身包含ScrollViewers,这是有道理的。他的建议(可行,但我们都同意似乎比它应该更复杂)是捕获并重新抛出后面代码中的滚动事件(并且可能必须处理计算滚动的偏移量)以便它可以冒泡到&#34; MainScrollViewer&#34;。

编辑2: 似乎实现此目的的唯一方法是使用后台代码来处理父级中的PreviewMouseWheel事件。这是有效的,但我如何实现相同的平移(用手指在触摸屏上滚动)?

3 个答案:

答案 0 :(得分:5)

为您的scrollview创建一个冒泡的scrollbehavior:

using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;

public sealed class BubbleScrollEvent : Behavior<UIElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
        base.OnDetaching();
    }

    void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (!e.Handled)
        {
            e.Handled = true;
            var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = UIElement.MouseWheelEvent };
            AssociatedObject.RaiseEvent(e2);
        }
    }
}

将此行为添加到您的滚动查看器:

 <ScrollViewer x:Name="Scroller">
                    <i:Interaction.Behaviors>
                        <ViewAddons:BubbleScrollEvent />
                    </i:Interaction.Behaviors>

答案 1 :(得分:4)

使用ScrollViewer的PreviewMouseWheel事件和ScrollToVerticalOffset方法......

private void ScrollViewerOnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    var scv = sender as ScrollViewer;
    if (scv == null) return;
    scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
    e.Handled = true;
}

答案 2 :(得分:0)

对于初学者,请确保您使用的是已存在的技术。这可能会解决您的问题。

<Grid HorizontalAlignment="Left" Height="300" Margin="10,10,0,0" VerticalAlignment="Top" Width="497" ScrollViewer.VerticalScrollBarVisibility="Visible" />

虽然如果没有解决问题,我知道这听起来很奇怪,请将网格和问题对象的背景颜色设置为#00000000。 (如果尚未指定颜色/画笔)

<Grid HorizontalAlignment="Left" Height="300" Margin="10,10,0,0" VerticalAlignment="Top" Width="497" Background="#00000000"/>

我知道它很奇怪,但是当我遇到这些问题时,它每次都有效。我不知道为什么会这样。与透明度有关。