是否有可能实现平滑滚动的WPF列表视图?

是否有可能在WPF listview实现平滑滚动,就像它在Firefox中的工作方式一样?
当Firefox浏览器包含所有listview项目,并按住鼠标中键(但不是释放),并拖动它,它应该平滑滚动listview项目。 当你释放它应该停止。

它看起来像这是不可能在winforms,但我想知道,如果它是在WPF中可用?

你可以实现平滑的滚动,但是你失去了物品的虚拟化,所以基本上你只有在列表中的元素很less的情况下才能使用这个技巧:

这里的信息: 在列表框上平滑滚动

你试过设置:

 ScrollViewer.CanContentScroll="False" 

在列表框?

这样的滚动是由面板而不是列表框处理…如果你这样做,你会失去虚拟化,但如果你有很多的内容,它可能会变慢。

确实有可能做你正在问的东西,尽pipe它需要相当数量的自定义代码。

通常在WPF中,ScrollViewer使用所谓的逻辑滚动(Logical Scrolling),这意味着它将逐项滚动而不是偏移量。 其他答案涵盖了一些可以将逻辑滚动行为更改为物理滚动行为的方法。 另一种方法是利用ScrollViwer和IScrollInfo公开的ScrollToVertialOffset和ScrollToHorizo​​ntalOffset方法。

为了实现更大的部分,滚动鼠标滚轮时,我们需要使用MouseDown和MouseMove事件。

 <ListView x:Name="uiListView" Mouse.MouseDown="OnListViewMouseDown" Mouse.MouseMove="OnListViewMouseMove" ScrollViewer.CanContentScroll="False"> .... </ListView> 

在MouseDown中,我们将logging当前的鼠标位置,我们将使用它作为相对点来确定我们滚动的方向。在鼠标移动中,我们将获得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; } 

有一些地方缺乏,因为这只是一个概念的certificate,但它肯定会让你开始正确的方向。 为了在鼠标从最初的MouseDown点移开时不断滚动,滚动逻辑可以进入DispatcherTimer或类似的东西。

尝试在ListView上将ScrollViewer.CanContentScroll附加属性设置为false 。 但是就像Pop Catalin说的那样,你失去了物品的虚拟化,这意味着列表中的所有物品都会立即被装载和填充,而不是当需要显示一组物品时 – 所以如果列表很大,可能会导致一些内存和性能问题。

如果你使用.NET 4.5(或4.0,如果你愿意黑客一点),那么这里有一个答案。

尝试将列表视图的高度设置为自动并将其包装在滚动查看器中。

 <ScrollViewer IsTabStop="True" VerticalScrollBarVisibility="Auto"> <ListView></ListView> </ScrollViewer> 

不要忘记提及ScrollViewer的高度希望这有助于….