"Бесконечная прокрутка" в ListView / избегание событий прокрутки повторного участника
Моя цель-имитировать "бесконечную прокрутку" в WPF ListView
. Я достиг этой цели с помощью некоторых далеко не идеальных методов, и я уверен, что есть лучший способ сделать это.
Под "бесконечной прокруткой" я подразумеваю следующее:
Предположим, что a ListView
имеет 20 элементов (упорядоченных 1, 2, 3, 4, ... 17, 18, 19, 20
). Когда пользователь прокручивает вниз один элемент, элемент в верхней части ListView
удаляется и помещается в конце ListView
, поэтому порядок элементов равен 2, 3, 4, 5, ... 18, 19, 20, 1
. Теперь, если пользователь прокручивает два пункта вниз, два верхних элементы удаляются и помещаются в конце таким образом, чтобы порядок элементов был 4, 5, 6, 7, ... 20, 1, 2, 3
. Теперь аналогично, если пользователь прокручивает один элемент вверх, элемент в нижней части ListView
удаляется и помещается в начало, так что порядок элементов равен 3, 4, 5, 6, ... 19, 20, 1, 2
.
Я достиг этой задачи со следующей функцией, назначенной событию ScrollChanged
из ScrollViewer
, которое я хочу быть "бесконечным":
// sv - the ScrollViewer to which this event handler is listening
// lv - the ListView associated with "sv"
bool handle_scroll = true;
private void inf_scroll(object sender, ScrollChangedEventArgs e) {
if (handle_scroll) {
for (int i = 0; i < e.VerticalChange; i++) {
object tmp = lv.Items[0];
lv.Items.RemoveAt(0);
lv.Items.Add(tmp);
handle_scroll = false;
}
for (int i = 0; i > e.VerticalChange; i--) {
object tmp = lv.Items[lv.Items.Count - 1];
lv.Items.RemoveAt(lv.Items.Count - 1);
lv.Items.Insert(0, tmp);
handle_scroll = false;
}
if(!handle_scroll){
sv.ScrollToVerticalOffset(sv.VerticalOffset - e.VerticalChange);
}
}
else {
handle_scroll = true;
}
}
Обратите внимание на переменную handle_scroll
. Я поставил это на место, потому что вызов sv.ScrollToVerticalOffset
вызовет весь inf_scroll
функция, вызываемая рекурсивно, если ее там не было.
Я знаю , что прокручивать ScrollViewer
в обработчике событий ScrollChanged
- плохая практика, поэтому я спрашиваю: есть ли лучший способ сделать это? Как я могу предотвратить рекурсивные вызовы inf_scroll
? Есть ли лучший способ имитировать "бесконечную прокрутку"?
1 ответ:
Хотя он явно не избегает прокрутки в обработчике
ScrollChanged
, Вы можете попробовать следующее:// sv - the ScrollViewer to which this event handler is listening // lv - the ListView associated with "sv" private void inf_scroll(object sender, ScrollChangedEventArgs e) { for (int i = 0; i < e.VerticalChange; i++) { object tmp = lv.Items[0]; lv.Items.RemoveAt(0); lv.Items.Add(tmp); } for (int i = 0; i > e.VerticalChange; i--) { object tmp = lv.Items[lv.Items.Count - 1]; lv.Items.RemoveAt(lv.Items.Count - 1); lv.Items.Insert(0, tmp); } lv.ScrollChanged -= inf_scroll; // remove the handler temporarily sv.ScrollToVerticalOffset(sv.VerticalOffset - e.VerticalChange); Dispatcher.BeginInvoke(DispatcherPriority.Send, new Action(() =>{ sv.ScrollChanged += inf_scroll; // add the handler back after the scrolling has occurred to avoid recursive scrolling })); }