是否有可能实现在WPF列表视图平滑滚动?是否有可能实现在WPF列表视图平滑滚动?(Is it pos

2019-05-13 16:00发布

是否有可能实现在WPF平滑滚动listview喜欢它是如何工作在Firefox?
当Firefox浏览器中包含的所有listview项目,按住鼠标中键(但不会释放),并拖动它,它应该平稳地滚动listview项目。 当你释放它应该停止。

看起来这是不可能的WinForms,但我想知道如果它是可用的WPF?

Answer 1:

您可以实现平滑滚动,但你失去了虚拟化项目,所以基本上你应该使用这种技术只有当你有列表中的几个要素:

资讯: 平滑滚动列表框上

你试过设置:

 ScrollViewer.CanContentScroll="False" 

列表框?

通过这种方式,滚动由面板,而不是列表框处理......你如果你这样做,但这样可能会比较慢,如果你有大量的内容失去虚拟化。



Answer 2:

这确实是可以做到你的要求,但它需要的自定义代码相当数量。

通常在WPF中ScrollViewer中使用所谓的逻辑滚动,这意味着它会通过项目,而不是一个偏移量来滚动项目。 其他答案介绍一些您可以更改逻辑滚动行为成物理滚动的方式。 另一种方法是利用双方ScrollViwer和IScrollInfo暴露ScrollToVertialOffset和ScrollToHorizo​​ntalOffset方法。

为了实现较大的部分,滚动按下鼠标滚轮时,我们需要利用鼠标按下和mousemove事件。

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

在鼠标按下,我们将记录当前鼠标的位置,我们将作为一个相对点使用,以确定我们在滚动的方向。在鼠标移动,我们要得到的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或类似的东西。



Answer 3:

尝试ScrollViewer.CanContentScroll连接属性设置为falseListView控件 。 但是,像流行克特林说,你输项目虚拟化,这意味着在列表中的所有项目将加载并立即填充,需要一组项目并不时显示的-所以,如果名单是巨大的,它可能会导致一些内存和性能问题。



Answer 4:

如果你(如果你愿意砍一点或4.0)使用.NET 4.5,然后有一个答案在这里 。



Answer 5:

尝试设置ListView的高度设置为auto,并在滚动浏览器加以包装。

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

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



文章来源: Is it possible to implement smooth scroll in a WPF listview?