ListView中的“无限滚动” /避免重入滚动事件

时间:2018-07-05 14:51:03

标签: c# wpf listview event-handling scrollviewer

我的目标是在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进行递归调用?有没有更好的方法来模拟“无限滚动”?

1 个答案:

答案 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
    }));
}