ScrollViewer鼠标滚轮无法正常工作

时间:2013-04-26 10:43:18

标签: c# .net wpf scrollviewer mousewheel

我目前正在开发我的第一个WPF项目并试图使listview可滚动。 起初我认为这可以通过简单地限制列表视图的宽度和高度来轻松完成,从而当内容超出其空间时强制滚动条自动出现。这看起来很好,但是由于处理过的PreviewMouseDown-Event(可以拖动列表的项目),它在选择项目后不起作用。

第二次尝试(使用ScrollViewer)

<ScrollViewer>
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"
              Height="450" Width="200"/>
</ScrollViewer>

当然,只要列表的内容大于其最大高度,就会产生第二个滚动条。选择项目后,拖动栏仍然无效。

第三次(非常愚蠢)尝试(禁用滚动条复制)

<ScrollViewer>
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"
              Height="450" Width="200"
              ScrollViewer.VerticalScrollBarVisibility="Disabled"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</ScrollViewer>

这删除了滚动条复制并启用了通过鼠标滚轮滚动但禁用了滚动条,因此您无法通过单击并拖动它来移动。

第四次尝试(ScrollViewer的常量)

<ScrollViewer Height="450" Width="200">
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"/>
</ScrollViewer>

从ListView中删除宽度/高度约束并将其移动到ScrollViewer。这将启用滚动条并删除重复项。不幸的是鼠标滚轮不再工作(拖动滚动条工作正常)。

有人可以向我解释为什么鼠标滚轮不再工作以及如何解决这个问题?

修改 也许我应该回到我的第一个解决方案。      显然,ListView的模板已经包含ScrollViewer。剩下的问题是,由于处理的PreviewMouseDown事件,我在选择项目后无法拖动滚动条(在这种情况下,通过鼠标滚轮滚动仍然有效)。我是否应该以不同的方式处理项目的拖动(在我想要添加滚动条之前,它对我来说很好)?或者有没有办法检测光标是否在滚动条上方(这样我就可以取消选择能够滚动的项目)? 或者还有其他建议吗?

6 个答案:

答案 0 :(得分:83)

这可能对你有帮助..

private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
   ScrollViewer scv = (ScrollViewer)sender;
   scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
   e.Handled = true;
 }

答案 1 :(得分:17)

这可能是最舒服的解决方案:

        <ListView.Template>
            <ControlTemplate>
                <ScrollViewer>
                    <ItemsPresenter></ItemsPresenter>
                </ScrollViewer>
            </ControlTemplate>
        </ListView.Template>

答案 2 :(得分:9)

<ScrollViewer Background="Transparent">

如果Background为null,则鼠标滚轮将无法在ScrollViewer上运行。您可以将背景设置为透明或其他值。

答案 3 :(得分:4)

就我而言:

<ScrollViewer ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
    <DataGrid x:Name="dataGrid" SelectionMode="Single" ItemsSource="{Binding}"  SelectedValuePath="{Binding Item}" AutoGenerateColumns="True">
    </DataGrid>
</ScrollViewer>

设计是在外部作用域中禁用VerticalScrollBarVisibility属性,即在ScrollViewer中

答案 4 :(得分:3)

对我来说这很有效:

<ListView.Template>
    <ControlTemplate>
        <!-- Empty template to allow ScrollViewer to capture mouse scroll -->
        <ItemsPresenter />
    </ControlTemplate>
</ListView.Template>

而不是:

<ListView.Template>
    <ControlTemplate>
        <ScrollViewer>
            <ItemsPresenter></ItemsPresenter>
        </ScrollViewer>
    </ControlTemplate>
</ListView.Template>

答案 5 :(得分:0)

我想向Rocky提供的解决方案添加一些评论。它对我来说很好用,但是后来我需要在其他窗口中使用它来滚动Grid。我遇到了一个问题:scrollviewer没有滚动到最底端。原因是由于尝试设置无效的VerticalOffset值。下面的代码对我来说很好(只是需要更改PreviewMouseWheel处理程序:

private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        ScrollViewer scroll = (ScrollViewer)sender;
        if (e.Delta < 0)
        {
            if (scroll.VerticalOffset - e.Delta <= scroll.ExtentHeight - scroll.ViewportHeight)
            {
                scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
            }
            else
            {
                scroll.ScrollToBottom();
            }
        }
        else
        {
            if (scroll.VerticalOffset + e.Delta > 0)
            {
                scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
            }
            else
            {
                scroll.ScrollToTop();
            }
        }
        e.Handled = true;
    }