如何判断CollectionView是通过代码还是用户手动触发滚动?
区分CollectionView的代码触发滚动与手动触发滚动
方法一:使用标记变量区分
这是最直接的实现方式,通过一个布尔变量标记当前滚动是否由代码触发:
- 定义一个私有布尔字段,用于标记滚动触发源
- 代码触发滚动前,将标记设为
true,滚动操作完成后再重置为false - 在
Scrolled事件回调中,通过这个标记判断滚动类型
示例代码:
private bool _isProgrammaticScroll; // 代码触发滚动的方法 private void TriggerScrollViaCode() { _isProgrammaticScroll = true; // 执行代码滚动操作,比如滚动到指定项 MyCollectionView.ScrollTo(targetItem, ScrollToPosition.Start); // 用Dispatcher延迟重置标记,确保Scrolled事件触发时标记仍有效 Dispatcher.DispatchAsync(() => _isProgrammaticScroll = false); } // Scrolled事件处理逻辑 private void OnCollectionViewScrolled(object sender, ScrolledEventArgs e) { if (_isProgrammaticScroll) { // 处理代码触发的滚动逻辑 return; } // 处理用户手动触发的滚动逻辑 }
方法二:自定义CollectionView子类(更优雅的封装)
如果需要在多个页面复用这个判断逻辑,可以封装一个自定义的CollectionView子类,内部维护触发标记:
public class TrackableCollectionView : CollectionView { public bool IsProgrammaticScroll { get; private set; } public override void ScrollTo(object item, object group, ScrollToPosition position, bool animate) { IsProgrammaticScroll = true; base.ScrollTo(item, group, position, animate); Dispatcher.DispatchAsync(() => IsProgrammaticScroll = false); } // 重写其他ScrollTo重载方法,逻辑一致 }
在XAML中使用这个自定义控件后,事件回调里直接读取标记即可:
private void OnTrackableCollectionViewScrolled(object sender, ScrolledEventArgs e) { var collectionView = sender as TrackableCollectionView; if (collectionView?.IsProgrammaticScroll == true) { // 代码触发的滚动 return; } // 用户手动触发的滚动 }
注意事项
- 必须用
Dispatcher延迟重置标记,因为ScrollTo是异步执行的,Scrolled事件会在方法返回后才触发,同步重置会导致标记提前失效。
内容的提问来源于stack exchange,提问作者binncheol
相关产品推荐
相关产品推荐

