scrollviewer里面的Listview阻止了scrollviewer滚动

时间:2012-01-19 20:21:52

标签: c# wpf listbox scrollviewer

我有一个滚动查看器,里面有几个列表框。问题是如果用户使用鼠标中键滚动滚动查看器,而鼠标位于列表视图上方。列表视图将其内部滚动查看器滚动到底部,然后继续捕获鼠标,防止包含滚动查看器滚动。

关于如何处理这个的任何想法?

5 个答案:

答案 0 :(得分:41)

之所以发生这种情况,是因为ListView的(实际上是ListBox)内容模板本身就会用ScrollViewer包装其项目。

最简单的方法是通过为内部Template删除自己的ListView来禁用它,不会创建ScrollViewer

    <ListView>
      <ListView.Template>
        <ControlTemplate>
          <ItemsPresenter></ItemsPresenter>
        </ControlTemplate>
      </ListView.Template>
      ...
    </ListView>
如果你在ListView中有一个ListView(这是我的情况),BTW也会发生同样的情况。

答案 1 :(得分:3)

您是否尝试停用ListView's ScrollBars

<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Disabled" />

答案 2 :(得分:3)

IMO,处理这种情况的最好方法是创建一个自定义控件:

     class MyScrollViewer : ScrollViewer
     {
         protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
         {
            base.OnPreviewMouseWheel(e);
            if (!e.Handled)
            {
                e.Handled = true;
                this.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
                {
                    RoutedEvent = UIElement.MouseWheelEvent,
                    Source = this
                });
            }
        }
    }

答案 3 :(得分:1)

some helpful answers的启发,我实现了一个实现,当内部祖先ScrollViewer(包括来自ListView,ListBox,DataGrid的祖先)滚动超过其顶部/底部时,将其滚动。

我将附加属性应用于App.xaml中的所有ScrollViewer:

<Style TargetType="ScrollViewer" BasedOn="{StaticResource {x:Type ScrollViewer}}">
    <Setter Property="local:ScrollViewerHelper.FixMouseWheel" Value="True" />
</Style>

附加属性检测滚动到顶部/底部的位置,并且发生滚动时,会在ScrollViewer的父级上引发鼠标滚轮事件。事件路由将其传递到外部ScrollViewer:

public static class ScrollViewerHelper
{
    // Attached property boilerplate
    public static bool GetFixMouseWheel(ScrollViewer scrollViewer) => (bool)scrollViewer?.GetValue(FixMouseWheelProperty);
    public static void SetFixMouseWheel(ScrollViewer scrollViewer, bool value) => scrollViewer?.SetValue(FixMouseWheelProperty, value);
    public static readonly DependencyProperty FixMouseWheelProperty =
        DependencyProperty.RegisterAttached("FixMouseWheel", typeof(bool), typeof(ScrollViewerHelper),
            new PropertyMetadata(OnFixMouseWheelChanged));
    // End attached property boilerplate

    static void OnFixMouseWheelChanged(DependencyObject d,
                                       DependencyPropertyChangedEventArgs e)
    {
        var scrollViewer = d as ScrollViewer;
        if (scrollViewer == null) return;

        scrollViewer.PreviewMouseWheel += (s2, e2) =>
        {
            var parent = scrollViewer.Parent as UIElement;
            bool hitTopOrBottom = HitTopOrBottom(e2.Delta, scrollViewer);
            if (parent is null || !hitTopOrBottom) return;

            var argsCopy = Copy(e2);
            parent.RaiseEvent(argsCopy);
        };
    }

    static bool HitTopOrBottom(double delta, ScrollViewer scrollViewer)
    {
        var contentVerticalOffset = scrollViewer.ContentVerticalOffset;

        var atTop = contentVerticalOffset == 0;
        var movedUp = delta > 0;
        var hitTop = atTop && movedUp;

        var atBottom =
            contentVerticalOffset == scrollViewer.ScrollableHeight;
        var movedDown = delta < 0;
        var hitBottom = atBottom && movedDown;

        return hitTop || hitBottom;
    }

    static MouseWheelEventArgs Copy(MouseWheelEventArgs e)
        => new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
        {
            RoutedEvent = UIElement.MouseWheelEvent,
            Source = e.Source,
        };
}

答案 4 :(得分:0)

如果将内部列表视图包装在滚动查看器中,则滚动将起作用。

<ListView ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
                <ListView>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </ScrollViewer>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>