在WPF listview中可以像在Firefox中那样实现平滑滚动吗?当Firefox浏览器包含所有listview项目时,按住鼠标中键(但不释放)并拖动它,它应该平滑地滚动listview项目。当释放时,它应该停止。看起来这在winforms中是不可能的,但是我想知道它在WPF中是否可用?
listview
kpbwa7wx1#
你可以实现平滑的滚动,但你失去了项目的虚拟化,所以基本上你应该使用这种技术,只有当你有几个元素在列表中:此处显示信息:Smooth scrolling on listbox
ScrollViewer.CanContentScroll="False"
r8uurelv2#
您所要求的确实是可以实现的,尽管这需要相当数量的自定义代码。通常在WPF中,ScrollViewer使用所谓的逻辑滚动,这意味着它将逐项滚动,而不是按偏移量滚动。其他答案涵盖了将逻辑滚动行为更改为物理滚动行为的一些方法。另一种方法是使用ScrollToVertialOffset和ScrollToHorizontalOffset方法,这两个方法由ScrollViwer和IScrollInfo公开。要实现更大的部分,即按下鼠标滚轮时的滚动,我们需要使用MouseDown和MouseMove事件。
<ListView x:Name="uiListView" Mouse.MouseDown="OnListViewMouseDown" Mouse.MouseMove="OnListViewMouseMove" ScrollViewer.CanContentScroll="False"> .... </ListView>
在MouseDown中,我们将记录当前鼠标位置,并将其用作相对点以确定滚动的方向。在鼠标移动中,我们将获取ListView的ScrollViwer组件,然后相应地滚动它。
private Point myMousePlacementPoint; private void OnListViewMouseDown(object sender, MouseButtonEventArgs e) { if (e.MiddleButton == MouseButtonState.Pressed) { myMousePlacementPoint = this.PointToScreen(Mouse.GetPosition(this)); } } private void OnListViewMouseMove(object sender, MouseEventArgs e) { ScrollViewer scrollViewer = ScrollHelper.GetScrollViewer(uiListView) as ScrollViewer; if (e.MiddleButton == MouseButtonState.Pressed) { var currentPoint = this.PointToScreen(Mouse.GetPosition(this)); if (currentPoint.Y < myMousePlacementPoint.Y) { scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - 3); } else if (currentPoint.Y > myMousePlacementPoint.Y) { scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + 3); } if (currentPoint.X < myMousePlacementPoint.X) { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 3); } else if (currentPoint.X > myMousePlacementPoint.X) { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + 3); } } } public static DependencyObject GetScrollViewer(DependencyObject o) { // Return the DependencyObject if it is a ScrollViewer if (o is ScrollViewer) { return o; } for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) { var child = VisualTreeHelper.GetChild(o, i); var result = GetScrollViewer(child); if (result == null) { continue; } else { return result; } } return null; }
它还缺少一些地方,因为它只是一个概念的证明,但它肯定会让你在正确的方向上开始。为了让它在鼠标从初始的MouseDown点移开后不断滚动,滚动逻辑可以进入DispatcherTimer或类似的东西。
hrirmatl3#
尝试将 ListView 上的 ScrollViewer.CanContentScroll 附加属性设置为 false。但是就像 Pop Catalin 所说的那样,您会失去项目虚拟化,这意味着列表中的所有项目都会立即加载和填充,而不是在需要显示一组项目时加载和填充-因此,如果列表很大,可能会导致一些内存和性能问题。
fnatzsnv4#
尝试设置列表视图的高度为自动并在滚动查看器中 Package 它.
<ScrollViewer IsTabStop="True" VerticalScrollBarVisibility="Auto"> <ListView></ListView> </ScrollViewer>
别忘了提到ScrollViewer的高度希望这能有所帮助....
deikduxw5#
我知道这篇文章已经有13年的历史了,但这仍然是人们想做的事情。在较新版本的.Net中,你可以设置**VirtualizingPanel.ScrollUnit="Pixel"**这样你就不会失去虚拟化,你可以按像素滚动,而不是按项目滚动。
VirtualizingPanel.ScrollUnit="Pixel"
5条答案
按热度按时间kpbwa7wx1#
你可以实现平滑的滚动,但你失去了项目的虚拟化,所以基本上你应该使用这种技术,只有当你有几个元素在列表中:
此处显示信息:Smooth scrolling on listbox
r8uurelv2#
您所要求的确实是可以实现的,尽管这需要相当数量的自定义代码。
通常在WPF中,ScrollViewer使用所谓的逻辑滚动,这意味着它将逐项滚动,而不是按偏移量滚动。其他答案涵盖了将逻辑滚动行为更改为物理滚动行为的一些方法。另一种方法是使用ScrollToVertialOffset和ScrollToHorizontalOffset方法,这两个方法由ScrollViwer和IScrollInfo公开。
要实现更大的部分,即按下鼠标滚轮时的滚动,我们需要使用MouseDown和MouseMove事件。
在MouseDown中,我们将记录当前鼠标位置,并将其用作相对点以确定滚动的方向。在鼠标移动中,我们将获取ListView的ScrollViwer组件,然后相应地滚动它。
它还缺少一些地方,因为它只是一个概念的证明,但它肯定会让你在正确的方向上开始。为了让它在鼠标从初始的MouseDown点移开后不断滚动,滚动逻辑可以进入DispatcherTimer或类似的东西。
hrirmatl3#
尝试将 ListView 上的 ScrollViewer.CanContentScroll 附加属性设置为 false。但是就像 Pop Catalin 所说的那样,您会失去项目虚拟化,这意味着列表中的所有项目都会立即加载和填充,而不是在需要显示一组项目时加载和填充-因此,如果列表很大,可能会导致一些内存和性能问题。
fnatzsnv4#
尝试设置列表视图的高度为自动并在滚动查看器中 Package 它.
别忘了提到ScrollViewer的高度希望这能有所帮助....
deikduxw5#
我知道这篇文章已经有13年的历史了,但这仍然是人们想做的事情。在较新版本的.Net中,你可以设置**
VirtualizingPanel.ScrollUnit="Pixel"
**这样你就不会失去虚拟化,你可以按像素滚动,而不是按项目滚动。