Рейтинг:
2
Graeme_Grant
Вот простое решение без MVVM, которое будет работать с VirtualizingStackPanel- протестировано со 100 000 элементами. Мы работаем непосредственно с ScrollViewer ListView. Будет работать даже при изменении размера списка.
1. Xaml
<Window
x:Class="PagingVirtualListView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Paging Virtualized ListView"
Height="300" Width="500" WindowStartupLocation="CenterScreen">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListView x:Name="PeopleList" ItemsSource="{Binding Persons}" >
<ListView.View>
<GridView>
<GridViewColumn Header="Avatar" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding AvatarUrl}" Margin="10" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="200" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
</GridView>
</ListView.View>
</ListView>
<StackPanel Grid.Column="1" Margin="10" VerticalAlignment="Center">
<Button Content="PGUP" Click="OnPgUpClick" Padding="10 5" Margin="10"/>
<Button Content="PGDn" Click="OnPgDnClick" Padding="10 5" Margin="10"/>
</StackPanel>
</Grid>
</Window>
2. Код-позади:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PeopleList.Loaded += PeopleList_Loaded;
DataContext = this;
Mock();
}
ScrollViewer lvScrollViewer;
public ObservableCollection<Person> Persons { get; set; }
= new ObservableCollection<Person>();
private Random rand = new Random();
private void Mock()
{
for (int i = 0; i < 100000; i++)
{
Persons.Add(new Person
{
AvatarUrl = "http://www.freepngimg.com/download/happy_person/2-2-happy-person-free-download-png.png",
Name = $"Person {i}",
Age = rand.Next(20, 60)
});
}
}
private void PeopleList_Loaded(object sender, RoutedEventArgs e)
{
PeopleList.Loaded -= PeopleList_Loaded;
// remember the ListView's Scrollviewer
lvScrollViewer = PeopleList.GetVisualChild<ScrollViewer>();
}
private void OnPgUpClick(object sender, RoutedEventArgs e)
{
lvScrollViewer.ScrollToVerticalOffset(
Math.Max(0, lvScrollViewer.VerticalOffset - lvScrollViewer.ViewportHeight));
}
private void OnPgDnClick(object sender, RoutedEventArgs e)
{
lvScrollViewer.ScrollToVerticalOffset(
Math.Min(lvScrollViewer.VerticalOffset + lvScrollViewer.ViewportHeight, Persons.Count - 1));
}
}
public static class HelperExtension
{
public static T GetVisualChild<T>(this Visual referenceVisual) where T : Visual
{
Visual child = null;
for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceVisual); i++)
{
child = VisualTreeHelper.GetChild(referenceVisual, i) as Visual;
if (child != null && (child.GetType() == typeof(T)))
break;
else if (child != null)
{
child = GetVisualChild<T>(child);
if (child != null && (child.GetType() == typeof(T)))
break;
}
}
return child as T;
}
}
public class Person
{
public string AvatarUrl { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Наслаждаться.
Member 11859517
Спасибо Graeme_Grant за вашу большую помощь.
его прокрутка страница за страницей, без сомнения, но мне нужно выбрать 1-й пункт 2-й страницы или последний пункт 1-й страницы. ты меня понял?
Graeme_Grant
Приведенный выше код делает то, что вы задали в своем вопросе.
Однако для новых требований самая трудная часть (изменение видового экрана) делается выше для вас.
Для новых требований эта часть довольно прямолинейна. Вы можете установить свой размер страницы вручную или использовать размер lvScrollViewer.ViewportHeight
(видимая область) для вычисления количества страниц и первого элемента каждой страницы и передачи этого значения в lvScrollViewer.ScrollToVerticalOffset
метод.
Но моя рекомендация-не делайте этого, это дезориентирует пользователя, и он пропустит важные данные. Нынешним методом они этого не сделают.
Правильный метод подкачки данных состоит только в том, чтобы заполнить ListView страницей и иметь панель навигации внизу с кнопками навигации вперед/назад и номер страницы.
Member 11859517
Спасибо,
тем не менее я не могу выбрать элемент, как я могу найти индекс на основе вертикального ofset или ViewportHeight
.
Graeme_Grant
Это совершенно другая проблема для нового вопроса. Вам нужно использовать ListView.SelectedItem property
и нет lvScrollViewer.ScrollToVerticalOffset
Один устанавливает выделение, другой изменяет видимые элементы.