我的目标是在WPF ListView
中模拟“无限滚动”。我已经通过一些不理想的方法完成了这项任务,并且我相信有更好的方法可以做到这一点。
“无限滚动”是指:
假设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
的{{1}}事件分配了以下功能来完成此任务:
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
进行递归调用?有没有更好的方法来模拟“无限滚动”?
答案 0 :(得分:2)
尽管它不能明确避免在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
}));
}