Действительно ли возможно реализовать гладкую прокрутку в WPF listview?

Есть ли способ, которым вы могли бы программно применить класс к объекту?

<object class="hasparams">

, а затем сделать

object.hasparams
38
задан Dave Clemmer 4 August 2011 в 02:26
поделиться

3 ответа

It is indeed possible to do what you're asking, though it will require a fair amount of custom code.

Normally in WPF a ScrollViewer uses what is known as Logical Scrolling, which means it's going to scroll item by item instead of by an offset amount. The other answers cover some of the ways you can change the Logical Scrolling behavior into that of Physical Scrolling. The other way is to make use of the ScrollToVertialOffset and ScrollToHorizontalOffset methods exposed by both ScrollViwer and IScrollInfo.

To implement the larger part, the scrolling when the mouse wheel is pressed, we will need to make use of the MouseDown and MouseMove events.

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

In the MouseDown, we are going to record the current mouse position, which we will use as a relative point to determine which direction we scroll in. In the mouse move, we are going to get the ScrollViwer component of the ListView and then Scroll it accordingly.

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

There's some areas it's lacking as it's just a proof of concept but it should definitely get you started in the right direction. To have it constantly scroll once the mouse is moved away from the initial MouseDown point, the scrolling logic could go into a DispatcherTimer or something similar.

11
ответ дан 27 November 2019 в 03:26
поделиться

Вы можете добиться плавной прокрутки, но потеряете виртуализацию элементов, поэтому в основном вам следует использовать этот метод, только если у вас мало элементов в списке:

Информация здесь: Плавная прокрутка включена listbox

Вы пробовали установить:

 ScrollViewer.CanContentScroll = "False"

в окне списка?

Таким образом, прокрутка выполняется панелью, а не списком ... Если вы сделаете это, вы потеряете виртуализацию, поэтому она может быть медленнее, если у вас много контента.

68
ответ дан 27 November 2019 в 03:26
поделиться

Попробуйте установить для присоединенного свойства ScrollViewer.CanContentScroll значение false в ListView . Но, как сказал Pop Catalin , вы теряете виртуализацию элементов, то есть все элементы в списке загружаются и заполняются сразу, а не тогда, когда необходимо отобразить набор элементов - поэтому, если список огромен, это могло вызвать проблемы с памятью и производительностью.

3
ответ дан 27 November 2019 в 03:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: