Можно ли реализовать плавную прокрутку в просмотре списка WPF? - PullRequest
38 голосов
/ 23 июня 2009

Возможно ли реализовать плавную прокрутку в WPF listview, например, как это работает в Firefox?
Когда браузер Firefox содержит все элементы listview и вы удерживаете среднюю кнопку мыши (но не отпускаете ее) и перетаскиваете ее, он должен плавно прокручивать элементы listview. Когда вы отпустите, он должен остановиться.

Похоже, что это невозможно в winforms, но мне интересно, доступно ли оно в WPF?

Ответы [ 5 ]

67 голосов
/ 23 июня 2009

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

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

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

ScrollViewer.CanContentScroll="False"

в списке?

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

10 голосов
/ 23 июня 2009

Действительно возможно сделать то, что вы просите, хотя это потребует значительного количества пользовательского кода.

Обычно в WPF ScrollViewer использует так называемую логическую прокрутку, что означает, что он будет прокручивать элемент за элементом, а не на величину смещения. Другие ответы охватывают некоторые способы, которыми вы можете изменить поведение логической прокрутки на поведение физической прокрутки. Другой способ заключается в использовании методов ScrollToVertialOffset и ScrollToHorizontOffset, предоставляемых как ScrollViwer, так и IScrollInfo.

Чтобы реализовать большую часть, прокрутку при нажатии колеса мыши, нам нужно будет использовать события MouseDown и MouseMove.

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

В MouseDown мы собираемся записать текущую позицию мыши, которую мы будем использовать в качестве относительной точки, чтобы определить направление прокрутки. При движении мыши мы получим компонент ScrollViwer объекта ListView и затем прокрутите его соответственно.

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 или что-то подобное.

4 голосов
/ 02 ноября 2015

Если вы используете .NET 4.5 (или 4.0, если хотите немного взломать), здесь есть ответ здесь .

3 голосов
/ 23 июня 2009

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

0 голосов
/ 16 мая 2015

попробуйте установить высоту списка в качестве авто и обернуть его в просмотрщик прокрутки.

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

Не забудьте упомянуть высоту ScrollViewer Надеюсь, это поможет ....

...