You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Forms中Shell页面与ListView导航点击事件异常触发问题

根因定位

该问题核心是Shell默认返回逻辑未触发事件解绑规则,导致ListView.ItemTapped的绑定被重复注册:点击自定义OK按钮返回时,你大概率在跳转代码中附带了绑定清理/页面销毁逻辑,而Shell自带返回箭头走的是系统默认导航栈弹出逻辑,没有执行你写的解绑代码,每次返回列表页都会多注册一次点击事件,最终出现点一次打开多个详情页的问题。

可行解决方案
  • 优先处理事件的绑定/解绑逻辑
    如果是后台代码用+=方式注册的ItemTapped事件,统一在OnAppearing中先解绑再绑定,在OnDisappearing中强制解绑,避免重复注册:
protected override void OnAppearing()
{
    base.OnAppearing();
    // 先移除已有绑定,避免重复
    ApptListView.ItemTapped -= OnListViewApptFinishedTapped;
    ApptListView.ItemTapped += OnListViewApptFinishedTapped;
}

protected override void OnDisappearing()
{
    base.OnDisappearing();
    // 页面消失时解绑事件
    ApptListView.ItemTapped -= OnListViewApptFinishedTapped;
}

如果是XAML绑定的Command,检查是否在OnAppearing中重复给ItemTappedCommand赋值,确保Command仅初始化一次。

  • 添加导航防抖锁
    替换你现在用的计数器方案,用布尔值做防抖,同时点击后立刻清空选中项,避免重复触发:
// 全局导航锁,避免同一时间多次触发跳转
private bool _isNavigating = false;

private async void OnListViewApptFinishedTapped(object sender, ItemTappedEventArgs e)
{
    // 导航中/选中项为空时直接拦截
    if (_isNavigating || e.Item == null) return;

    _isNavigating = true;
    // 你的详情页跳转逻辑
    await Shell.Current.GoToAsync("你的详情页路由");
    // 跳转完成后重置锁
    _isNavigating = false;
    // 清空选中项,避免下次点击同一条目不触发事件
    ((ListView)sender).SelectedItem = null;
}
  • 配置列表页缓存策略
    在列表页的XAML根节点添加Shell缓存配置,让列表页实例仅创建一次,避免每次导航回来重新初始化绑定:
<ContentPage 
    ...
    Shell.NavigationCacheBehavior="OnExternalNavigation"
    Shell.Preserve="True">
  • 排查单例ViewModel的订阅逻辑
    如果你的列表页绑定的是全局单例ViewModel,检查ViewModel中是否有和列表点击相关的订阅事件,确保在页面OnDisappearing时同步取消订阅,避免重复触发。

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:36:01