My goal is to simulate "infinite scrolling" in a WPF ListView
. I have achieved this task with some less-than-ideal methods, and I'm sure there is a better way to do it.
by "infinite scrolling" I mean the following:
Let's say a ListView
has 20 items (ordered 1, 2, 3, 4, ... 17, 18, 19, 20
). When the user scrolls down one item, the item at the top of the ListView
is removed and placed at the end of the ListView
so the order of the items is 2, 3, 4, 5, ... 18, 19, 20, 1
. Now if the user scrolls down two items, the top two items are removed and placed at the end so the order of the items is 4, 5, 6, 7, ... 20, 1, 2, 3
. Now, similarly, if the user scrolls up one item, the item at the bottom of the ListView
is removed and placed at the beginning so the order of the items is 3, 4, 5, 6, ... 19, 20, 1, 2
.
I have achieved this task with the following function assigned to the ScrollChanged
event of the ScrollViewer
I wish to be "infinite":
// 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;
}
}
Notice the variable handle_scroll
. I put this in place because the call to sv.ScrollToVerticalOffset
will cause the entire inf_scroll
function to be called recursively if it was not there.
I know it is bad practice to scroll the ScrollViewer
in a ScrollChanged
event handler, so that's why I'm asking: is there a better way to do this? How can I prevent the recursive calls to inf_scroll
? Is there a better way to simulate "infinite scrolling"?
Though it does not explicitly avoid scrolling in the ScrollChanged
handler, you could try the following:
// 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
}));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With