ScrollViewer 鼠标滚轮不滚动
Posted
技术标签:
【中文标题】ScrollViewer 鼠标滚轮不滚动【英文标题】:ScrollViewer mouse wheel not scrolling 【发布时间】:2013-04-20 12:21:10 【问题描述】:我目前正在处理我的第一个 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 滚动仍然有效),我无法在选择项目后拖动滚动条。我是否应该以不同的方式处理项目的拖动(在想要添加滚动条之前,它对我来说效果很好)?或者有没有办法检测光标是否在滚动条上方(所以我可以取消选择启用滚动的项目)?
或者有其他建议吗?
【问题讨论】:
【参考方案1】:这可能对你有帮助..
private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
ScrollViewer scv = (ScrollViewer)sender;
scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
e.Handled = true;
【讨论】:
很好,这行得通 - 谢谢。但我仍然不确定,在 ScrollViewer 中使用 ListView 是否是好的样式(参见上面的编辑部分)。 我发现将e.Delta
除以 10 可以使滚动的粒度更细(不那么粗)。 (不过答案很好!)【参考方案2】:
这可能是最舒服的解决方案:
<ListView.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListView.Template>
【讨论】:
最佳解决方案。可能还可以将 Itemspresenter 放入Grid
或 DockPanel
我的解决方案遇到了一个小问题。标题现在消失了。有什么建议吗?
@ShalvinAbraham 什么标题? Listview 没有我知道的标题?
我是 WPF 新手,所以可能是我的误解.. 我使用 ListView 作为: 对我来说这很有效:
<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>
【讨论】:
【参考方案4】:<ScrollViewer Background="Transparent">
如果Background
为空,鼠标滚轮将无法在ScrollViewer
上工作。您可以将Background
设置为Transparent
或其他值。
【讨论】:
这仅适用于我,如果鼠标指针位于滚动条上方,但如果它位于内容上方则无效【参考方案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
。
【讨论】:
这应该是公认的答案。它工作简单。谢谢! 同意。这是唯一对我有用的答案!谢谢!【参考方案6】:我想对 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;
【讨论】:
以上是关于ScrollViewer 鼠标滚轮不滚动的主要内容,如果未能解决你的问题,请参考以下文章
ListBox有个滚动条,ScrollViewer 有个滚动条
允许在内部水平滚动 ScrollViewer 内垂直滚动外部 ScrollViewer
wpf 中scrollviewer 中放置个LISTBOX,当焦点在LISTBOX时候,滚动鼠标不响应Scrollviewer的鼠标滚动