C# ScrollViewer 鼠标滚轮不工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16234522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:28:40  来源:igfitidea点击:

ScrollViewer mouse wheel not working

c#.netwpfscrollviewermousewheel

提问by sadeniju

I am currently working on my first WPF project and trying to make a listview scrollable. At first I thought this could be easily done by simply limiting the listview's width and height and thus forcing a scrollbar to appear automatically whenever the content exceeds its space. This seemed fine at first but due to the handled PreviewMouseDown-Event (which enables dragging the list's items) it doesn't work after selecting an item.

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

Second attempt(using ScrollViewer)

第二次尝试(使用 ScrollViewer)

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

Of course, this resulted in a second scrollbar whenever the list's content became larger than its max height. And dragging the bar still didn't work after selecting an item.

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

Third(quite foolish) attempt(disabling scrollbar duplicate)

第三次(相当愚蠢的)尝试(禁用滚动条重复)

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

This removed the scrollbar duplicate and enabled scrolling via mouse wheel but disabled the scrollbar, so you couldn't move by clicking and dragging it.

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

Fourth attempt(constant size of the ScrollViewer)

第四次尝试(ScrollViewer 的恒定大小)

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

Removed the width/height constraint from the ListView and moved it to the ScrollViewer. This enables the scrollbar and removes the duplicate. Unfortunately the mouse wheel doesn't work anymore (dragging the scroll bar works fine).

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

Could somebody please explain to me why the mouse wheel doesn't work anymore and how to fix this?

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

EditMaybe I should go back to my first solution. Obviously, the ListView's template already contains a ScrollViewer. The remaining problem would then be that I cannot drag the scrollbar after selecting an item because of the handled PreviewMouseDown event (scrolling via mousewheel still works in that case). Should I handle the dragging of items differently (it worked fine for me, before wanting to add a scrollbar)? Or is there a way to detect if the cursor is above the scrollbar (so I could then deselect the item which enables scrolling)? Or are there any other suggestions?

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

采纳答案by Rocky

This may help you..

这可能会帮助你..

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

回答by Dbl

This would probably be the most comfortable solution :

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

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

回答by 665

<ScrollViewer Background="Transparent">

If Background is null, the mouse wheel will not work on ScrollViewer. You can set the Background to Transparent or some other value.

如果 Background 为 null,则鼠标滚轮将不会在 ScrollViewer 上工作。您可以将背景设置为透明或其他值。

回答by Maksim Rodkin

in my case :

就我而言:

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

the design was in disabling VerticalScrollBarVisibility attribute in outer scope , i.e. in ScrollViewer

设计是在外部范围内禁用 VerticalScrollBarVisibility 属性,即在 ScrollViewer

回答by J Pollack

For me this worked:

对我来说这有效:

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

instead of this:

而不是这个:

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

回答by Ruzaki

I want to add some comment to the solution Rocky provided. It worked fine for me, but later I needed to use it in a different window to scroll Grid. I faced a problem: the scrollviewer did not scroll to the bottom end. The reason was because of attempts to set the invalid VerticalOffset value. The code below works fine for me (just need to change PreviewMouseWheel handler:

我想对 Rocky 提供的解决方案添加一些评论。它对我来说很好用,但后来我需要在不同的窗口中使用它来滚动网格。我遇到了一个问题: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;
    }