.NET 7 MAUI更新ListView绑定的ObservableCollection时出现空引用异常
.NET 7 MAUI Android ListView 空引用异常问题分析与解决方案
问题现象
首次运行应用时数据加载正常,但点击按钮清空ObservableCollection再添加新数据时,Android端触发空引用异常,Windows端无此问题。切换ListViewCachingStrategy为RecycleElement后问题消失。
问题原因
这个情况大概率是**.NET 7 MAUI Android端ListView在默认RetainElement缓存策略下的已知BUG**:
- 默认的
RetainElement模式会保留每个Cell的实例,当清空集合再添加新数据时,旧Cell可能未正确解绑绑定关系,导致后续绑定新数据时出现空引用。 RecycleElement模式下Cell会被复用,系统会正确处理Cell的绑定生命周期,因此规避了该问题。
解决方案
方案1:使用RecycleElement缓存策略(推荐)
直接在ListView中指定缓存策略,这不仅能解决空引用问题,还能提升ListView的性能(尤其数据量大时):
<ListView ItemsSource="{Binding CurrentData}" CachingStrategy="RecycleElement"> <ListView.ItemTemplate> <DataTemplate> <ImageCell ImageSource="{Binding Description}" Text="{Binding Name}" Detail="{Binding Description}" /> </DataTemplate> </ListView.ItemTemplate> </ListView>
方案2:替换整个ObservableCollection实例
修改ViewModel实现INotifyPropertyChanged,更新数据时直接赋值新的ObservableCollection,触发ListView重新绑定:
修改SomeDataViewModel.cs:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; namespace ListViewBugSample.ViewModels { public class SomeDataViewModel : INotifyPropertyChanged { private ObservableCollection<SomeData> _currentData; public ObservableCollection<SomeData> CurrentData { get => _currentData; set { if (_currentData != value) { _currentData = value; OnPropertyChanged(); } } } public SomeDataViewModel() { CurrentData = new ObservableCollection<SomeData>() { new() { Description = "Desc1", Name = "Name1"}, new() { Description = "Desc2", Name = "Name2" }, new() { Description = "Desc3", Name = "Name3" } }; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class SomeData { public string Name { get; set; } public string Description { get; set; } } }
修改MainPage.xaml.cs的更新方法:
private void UpdateListViewData(object sender, EventArgs e) { var newData = new ObservableCollection<SomeData> { new() { Description = "NewData1", Name = "NewName1"}, new() { Description = "NewData2", Name = "NewName2" }, new() { Description = "NewData3", Name = "NewName3" } }; _listViewModelData.CurrentData = newData; }
方案3:升级到更高版本的MAUI
该问题在.NET 8及后续版本的MAUI中已被修复,如果项目允许,升级到.NET 8+即可解决,无需修改现有代码逻辑。
结论
你的代码实现本身没有明显错误,这个空引用异常属于MAUI Android端在.NET 7版本的已知BUG。优先推荐使用RecycleElement缓存策略,既解决问题又提升性能;若需保留RetainElement模式,可选择替换集合实例或升级MAUI版本。
内容的提问来源于stack exchange,提问作者Ggilabert
相关产品推荐
相关产品推荐

