Можно ли реализовать плавную прокрутку в просмотре списка WPF?
Можно ли реализовать плавную прокрутку в WPF listview
например, как это работает в Firefox?
Когда браузер Firefox содержал все listview
элементы и удерживая среднюю кнопку мыши (но не отпустить), и перетащите его, он должен плавно прокручивать listview
Предметы. Когда вы отпустите, он должен остановиться.
Похоже, что это невозможно в winforms, но мне интересно, если это доступно в WPF?
6 ответов
Вы можете добиться плавной прокрутки, но вы потеряете виртуализацию элементов, поэтому в основном вы должны использовать эту технику, только если у вас есть несколько элементов в списке:
Информация здесь: Плавная прокрутка в списке
Вы пробовали установить:
ScrollViewer.CanContentScroll="False"
в окне списка?
Таким образом, прокрутка обрабатывается панелью, а не списком... Вы теряете виртуализацию, если делаете это, хотя это может быть медленнее, если у вас много контента.
Я знаю, что этому посту 13 лет, но люди все еще хотят это сделать. в более новых версиях .Net вы можете установить
VirtualizingPanel.ScrollUnit="Pixel"
таким образом, вы не потеряете виртуализацию и получите прокрутку на пиксель, а не на элемент.
Это действительно возможно сделать то, что вы просите, хотя это потребует значительного количества пользовательского кода.
Обычно в 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 или что-то подобное.
Попробуйте установить для присоединенного свойства ScrollViewer.CanContentScroll значение false в ListView. Но, как сказал Pop Catalin, вы теряете виртуализацию элементов, то есть все элементы в списке загружаются и заполняются одновременно, а не тогда, когда необходимо отобразить набор элементов - поэтому, если список огромен, это может привести к некоторой памяти и проблемы с производительностью.
Если вы используете.NET 4.5 (или 4.0, если хотите немного взломать), здесь есть ответ.
Попробуйте установить высоту списка в качестве автоматического и обернуть его в просмотрщик прокрутки.
<ScrollViewer IsTabStop="True" VerticalScrollBarVisibility="Auto">
<ListView></ListView>
</ScrollViewer>
Не забудьте упомянуть высоту ScrollViewer Надеюсь, это поможет....