Xamarin中Telerik ListView滑动展开时如何强制重绘当前项
问题场景
为搭建最小可复现示例,已创建完成绑定的Record类,当列表项被滑动时会显示[$]按钮。点击该按钮可正常关闭滑动状态,更新列表项的参考代码如下:
public ICommand ClickCommand { get; } private void OnClick(Record record) => onToggle(record); bool _toggled = false; private void onToggle(Record record) { _toggled = !_toggled; if(_toggled) { Title = "Toggled"; BackgroundColor = Color.LightSalmon; } else { Title = "Normal"; BackgroundColor = Color.Transparent; } ListView.EndItemSwipe(); }

经测试绑定逻辑本身正常,但实际需要实现的效果是:保持项的滑动展开状态,让卡片的背景色立即生效。注释掉ListView.EndItemSwipe();代码后,滑动状态可保持展开,此时点击[$]按钮仅会重绘按钮本身,卡片不会触发重绘,只有点击卡片关闭滑动状态后才会刷新:
核心诉求:当列表项仍处于滑动展开状态时,如何强制刷新项卡片,即在操作触发的第3帧而非关闭滑动后的第4帧完成重绘?
解决方法
这是ListView滑动交互的默认机制导致的:项处于滑动展开状态时,框架会优先响应滑动操作区的UI更新,主内容区的属性变更通知会被暂时挂起,直到滑动状态完全退出才会批量执行重绘。不需要修改控件源码,通过以下方式即可实现展开状态下的立即刷新:
- 单元素强制重绘(性能最优)
点击按钮完成业务属性赋值后,获取当前项对应的ViewCell实例,调用ForceLayout()方法强制该单元格立即执行布局和重绘,不需要调用EndItemSwipe()关闭滑动状态。参考修改后的代码:
该方法只会重绘当前操作的单个项,不会影响其他列表项的滑动状态,性能开销最小。// 点击命令传参时可直接携带当前项索引,也可通过数据源查找对应索引 int recordIndex = Records.IndexOf(record); if (ListView.TemplatedItems.GetOrCreateContent(recordIndex, record) is ViewCell targetCell) { targetCell.ForceLayout(); // 安卓平台下如果上述调用不生效,额外调用原生视图的Invalidate方法即可 #if ANDROID (targetCell.Handler?.PlatformView as Android.Views.View)?.Invalidate(); #endif } - MVVM适配方案
如果不想在后台代码中查找控件实例,可以给绑定的Record模型增加一个RefreshVersion整型属性,每次修改卡片业务属性时同步对该值+1;再给列表项的根容器添加绑定触发器,监听RefreshVersion的变更,触发时自动调用自身的ForceLayout()方法即可,逻辑和上述方法一致,不需要编写后台控件查找逻辑。
避坑提示:不要通过重新赋值
ItemsSource、调用列表全局刷新方法实现需求,这类操作会重置所有列表项的滑动状态,性能损耗也远大于单元素强制重绘。
内容的提问来源于stack exchange,提问作者IV.
相关产品推荐
相关产品推荐

