ScrollViewer鼠标滚轮不滚动

问题描述 投票:58回答:6

我目前正在做我的第一个WPF项目,并尝试着做一个新的项目。ListView 起初我以为可以通过简单地限制 "可滚动 "来实现。ListView的宽度和高度,从而迫使滚动条在内容超过其空间时自动出现。起初这似乎很好,但由于被处理了的 PreviewMouseDown 事件(可以拖动列表中的项目),但在选择项目后就不工作了。

第二次尝试 (使用 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 事件(在这种情况下,通过MouseWheel滚动仍然可以工作)。我是否应该以不同的方式来处理项目的拖动(在我想添加滚动条之前,它工作得很好)?或者有什么方法可以检测到光标是否在滚动条之上(这样我就可以取消选择可以滚动的项目)? 或者有其他建议吗?

c# wpf xaml scrollviewer mousewheel
6个回答
95
投票

这可能对你有帮助。

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

19
投票

这可能是最舒适的解决方案。

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

11
投票

对我来说,这很有效。

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

9
投票
<ScrollViewer Background="Transparent">

如果... Background 为空,鼠标滚轮将无法在 ScrollViewer. 您可以设置 BackgroundTransparent 或其他数值。


5
投票

在我的案例中,这对我很有帮助。

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


1
投票

我想对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;
}
© www.soinside.com 2019 - 2024. All rights reserved.