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

MAUI ListView在Android滚动时崩溃异常,求助排查问题

问题描述

基于MAUI开发Android应用原型时,ListView组件出现异常:当列表项数量超出屏幕需快速滚动时应用崩溃,底层Android错误为java.lang.IllegalStateException: The specified child already has a parent,缓慢滚动则无此问题。

尝试将ListView的CachingStrategy设置为"RecycleElementAndDataTemplate"可解决崩溃,但会导致单选按钮滚动出视图后丢失选中状态,还存在列表项文本消失等问题。

相关代码

ListView XAML代码

<ListView ItemsSource="{Binding Devices}"
          Style="{StaticResource ListViewSimpleStyle}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell x:DataType="local:DeviceEntryModel">
        <RadioButton IsChecked="{Binding IsChecked, Mode=TwoWay}"
                      GroupName="Devices">
          <RadioButton.Content>
              <Label BindingContext="{Binding Source={RelativeSource AncestorType={x:Type RadioButton}}, Path=BindingContext}"
                      Text="{Binding Name}"
                      IsEnabled="{Binding Source={RelativeSource AncestorType={x:Type RadioButton}}, Path=IsEnabled}" />
          </RadioButton.Content>
        </RadioButton>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

模型类代码

public partial class DeviceEntryModel : ObservableObject
{
  public DeviceEntry DeviceEntry { get; init; }

  public string Name => DeviceEntry.Name;

  public string Address => DeviceEntry.Address;

  [ObservableProperty]
  bool isChecked;
}
问题原因与解决办法

核心问题

崩溃的根源在于Label手动设置BindingContext的方式引发视图复用冲突:

  • RadioButton的Content区域默认继承RadioButton的BindingContext(即DeviceEntryModel),额外通过RelativeSource手动指定Label的BindingContext属于冗余操作。
  • 当ListView快速滚动触发视图复用(即使默认缓存策略)时,这种冗余绑定会导致Label控件被错误地重复关联到不同的父容器,触发Android底层的The specified child already has a parent异常。

而设置RecycleElementAndDataTemplate后出现的选中状态丢失、文本消失问题,是因为视图复用过程中,错误的绑定逻辑导致控件无法正确从模型同步最新状态。

修复步骤

1. 简化Label的绑定逻辑

删除Label上冗余的BindingContext设置,直接利用继承的上下文绑定数据:

<ListView ItemsSource="{Binding Devices}"
          Style="{StaticResource ListViewSimpleStyle}">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell x:DataType="local:DeviceEntryModel">
        <RadioButton IsChecked="{Binding IsChecked, Mode=TwoWay}"
                      GroupName="Devices">
          <RadioButton.Content>
              <!-- 移除手动设置的BindingContext,直接继承RadioButton的上下文 -->
              <Label Text="{Binding Name}"
                      IsEnabled="{Binding Source={RelativeSource AncestorType={x:Type RadioButton}}, Path=IsEnabled}" />
          </RadioButton.Content>
        </RadioButton>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

2. 恢复默认缓存策略(或使用RecycleElement)

移除CachingStrategy="RecycleElementAndDataTemplate"设置,使用ListView默认的缓存策略即可。若需优化性能,可设置为CachingStrategy="RecycleElement"——此时因为绑定逻辑已修复,视图复用会正确同步模型的IsChecked状态,不会出现选中状态丢失问题。

3. 确认数据源类型正确性

确保Devices是ObservableCollection<DeviceEntryModel>类型(而非ObservableCollection<DeviceEntry>),保证每个列表项的上下文都是DeviceEntryModel,绑定才能正常生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:20:55