如何以编程方式滚动WPF列表视图?

时间:2021-09-13 04:29:29

Is it possible to programmatically scroll a WPF listview? I know winforms doesn't do it, right?

是否可以以编程方式滚动WPF列表视图?我知道winforms不会这样做,对吧?

I am talking about say scrolling 50 units up or down, etc. Not scrolling an entire item height at once.

我说的是向上或向下滚动50个单位等。不要一次滚动整个项目高度。

2 个解决方案

#1


28  

Yes, you'll have to grab the ScrollViwer from the ListView, or but once you have access to that, you can use the methods exposed by it or override the scrolling. You can also scroll by getting the main content area and using it's implementation of the IScrollInfo interface.

是的,您必须从ListView中获取ScrollViwer,或者只要您有权访问它,就可以使用它公开的方法或覆盖滚动。您还可以通过获取主要内容区域并使用它的IScrollInfo接口实现来滚动。

Here's a little helper to get the ScrollViwer component of something like a ListBox, ListView, etc.

这里有一个小帮手可以获得类似ListBox,ListView等的ScrollViwer组件。

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

And then you can just use .LineUp() and .LineDown() like this:

然后你可以像这样使用.LineUp()和.LineDown():

private void OnScrollUp(object sender, RoutedEventArgs e)
{
    var scrollViwer = GetScrollViewer(uiListView) as ScrollViewer;

    if (scrollViwer != null)
    {
       // Logical Scrolling by Item
       // scrollViwer.LineUp();
       // Physical Scrolling by Offset
       scrollViwer.ScrollToVerticalOffset(scrollViwer.VerticalOffset + 3);
    }
}

private void OnScrollDown(object sender, RoutedEventArgs e)
{
    var scrollViwer = GetScrollViewer(uiListView) as ScrollViewer;

    if (scrollViwer != null)
    {
        // Logical Scrolling by Item
        // scrollViwer.LineDown();
        // Physical Scrolling by Offset
        scrollViwer.ScrollToVerticalOffset(scrollViwer.VerticalOffset + 3);
    }
}


<DockPanel>
    <Button DockPanel.Dock="Top"
            Content="Scroll Up"
            Click="OnScrollUp" />
    <Button DockPanel.Dock="Bottom"
            Content="Scroll Down"
            Click="OnScrollDown" />
    <ListView x:Name="uiListView">
        <!-- Content -->
    </ListView>
</DockPanel>

The Logical scrolling exposed by LineUp and LineDown do still scroll by item, if you want to scroll by a set amount you should use the ScrollToHorizontal/VerticalOffset that I've used above. If you want some more complex scrolling too, then take a look at the answer I've provided in this other question.

LineUp和LineDown公开的逻辑滚动仍然按项目滚动,如果你想按设定的数量滚动,你应该使用我上面使用过的ScrollToHorizo​​ntal / VerticalOffset。如果你想要一些更复杂的滚动,那么看看我在另一个问题中提供的答案。

#2


4  

Have you tried ScrollIntoView? Alternatively, if it's not a specific item you brought into view, but an offset from the current position, you can use BringIntoView.

你试过ScrollIntoView吗?或者,如果它不是您进入视图的特定项目,但是偏离当前位置,则可以使用BringIntoView。

#1


28  

Yes, you'll have to grab the ScrollViwer from the ListView, or but once you have access to that, you can use the methods exposed by it or override the scrolling. You can also scroll by getting the main content area and using it's implementation of the IScrollInfo interface.

是的,您必须从ListView中获取ScrollViwer,或者只要您有权访问它,就可以使用它公开的方法或覆盖滚动。您还可以通过获取主要内容区域并使用它的IScrollInfo接口实现来滚动。

Here's a little helper to get the ScrollViwer component of something like a ListBox, ListView, etc.

这里有一个小帮手可以获得类似ListBox,ListView等的ScrollViwer组件。

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

And then you can just use .LineUp() and .LineDown() like this:

然后你可以像这样使用.LineUp()和.LineDown():

private void OnScrollUp(object sender, RoutedEventArgs e)
{
    var scrollViwer = GetScrollViewer(uiListView) as ScrollViewer;

    if (scrollViwer != null)
    {
       // Logical Scrolling by Item
       // scrollViwer.LineUp();
       // Physical Scrolling by Offset
       scrollViwer.ScrollToVerticalOffset(scrollViwer.VerticalOffset + 3);
    }
}

private void OnScrollDown(object sender, RoutedEventArgs e)
{
    var scrollViwer = GetScrollViewer(uiListView) as ScrollViewer;

    if (scrollViwer != null)
    {
        // Logical Scrolling by Item
        // scrollViwer.LineDown();
        // Physical Scrolling by Offset
        scrollViwer.ScrollToVerticalOffset(scrollViwer.VerticalOffset + 3);
    }
}


<DockPanel>
    <Button DockPanel.Dock="Top"
            Content="Scroll Up"
            Click="OnScrollUp" />
    <Button DockPanel.Dock="Bottom"
            Content="Scroll Down"
            Click="OnScrollDown" />
    <ListView x:Name="uiListView">
        <!-- Content -->
    </ListView>
</DockPanel>

The Logical scrolling exposed by LineUp and LineDown do still scroll by item, if you want to scroll by a set amount you should use the ScrollToHorizontal/VerticalOffset that I've used above. If you want some more complex scrolling too, then take a look at the answer I've provided in this other question.

LineUp和LineDown公开的逻辑滚动仍然按项目滚动,如果你想按设定的数量滚动,你应该使用我上面使用过的ScrollToHorizo​​ntal / VerticalOffset。如果你想要一些更复杂的滚动,那么看看我在另一个问题中提供的答案。

#2


4  

Have you tried ScrollIntoView? Alternatively, if it's not a specific item you brought into view, but an offset from the current position, you can use BringIntoView.

你试过ScrollIntoView吗?或者,如果它不是您进入视图的特定项目,但是偏离当前位置,则可以使用BringIntoView。