maui
maui copied to clipboard
Issue with ListView and ObservableCollection
Description
When using a ObservableCollection in my project and displaying via a ListView, I have an issue when clearing the content of the ObservableCollection.
When calling incidentList.Clear(); it works fine on Android, but on iOS and MacOS I get the error "Object reference not set to an instance of an object."
Steps to Reproduce
code used that generates error:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DsfrsApp.Models;
using Newtonsoft.Json;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Xml;
namespace DsfrsApp.ViewModel;
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
ObservableCollection<IncidentCategoryModel> incidentCategories;
[ObservableProperty]
ObservableCollection<Item> items;
[ObservableProperty]
bool listRefreshing = false;
public RelayCommand ReloadTaskCommand { get; }
public MainViewModel()
{
ReloadTaskCommand = new RelayCommand(GetIncidents);
incidentCategories = new ObservableCollection<IncidentCategoryModel>();
items = new ObservableCollection<Item>();
}
async void GetIncidents()
{
await getIncidentDetails("https://www.somesite.com/rss-feed.xml");
}
async Task getIncidentDetails(string feedUrl)
{
ListRefreshing = true;
HttpClient client = new()
{
Timeout = new TimeSpan(0, 0, 20)
};
client.DefaultRequestHeaders.UserAgent.Clear();
client.DefaultRequestHeaders.Add("User-Agent", "DsfrAppTest");
await Task.Run(() =>
{
using var webResponse = client.GetAsync(feedUrl, HttpCompletionOption.ResponseHeadersRead);
using var downloadStream = webResponse.Result.Content.ReadAsStreamAsync().Result;
StreamReader reader = new StreamReader(downloadStream);
string xmlData = reader.ReadToEnd();
XmlDocument xmlDocument = new();
xmlDocument.LoadXml(xmlData);
var jsonText = JsonConvert.SerializeXmlNode(xmlDocument);
var incidents = Incident.FromJson(jsonText);
Items.Clear();
foreach (var incident in incidents.Rss.Channel.Item.Take(500))
{
Items.Add(incident);
}
var catDetail =
from item in Items
group item by item.Title into catList
select new
{
Title = catList.Key,
Count = catList.Count()
};
IncidentCategories.Clear();
ListRefreshing = false;
foreach (var cat in catDetail)
{
IncidentCategories.Add(new IncidentCategoryModel()
{
ItemCount = cat.Count,
Title = cat.Title
});
}
});
}
}
MainView.Xml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DsfrsApp.MainPage"
xmlns:viewmodel="clr-namespace:DsfrsApp.ViewModel"
x:DataType="viewmodel:MainViewModel"
xmlns:models="clr-namespace:DsfrsApp.Models">
<StackLayout
Padding="8"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Button
x:Name="btnFetch"
Text="Fetch Data"
Command="{Binding ReloadTaskCommand}"
Margin="8"/>
<ListView
ItemsSource="{Binding IncidentCategories}"
HasUnevenRows="True"
VerticalOptions="FillAndExpand"
ItemSelected="ListView_ItemSelected"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding ReloadTaskCommand}"
IsRefreshing="{Binding ListRefreshing, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate
x:DataType="models:IncidentCategoryModel">
<ViewCell>
<Grid
Padding="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle
WidthRequest="60"
HeightRequest="60"
BackgroundColor="lightblue"
Margin="8"
Grid.Column="0"
Grid.RowSpan="2" />
<Label Grid.Column="1"
Grid.Row="0"
Text="{Binding Title}"
FontAttributes="Bold"
FontSize="Title"/>
<Label Grid.Column="1"
Grid.Row="1"
Text="{Binding itemCountText}"
FontSize="Subtitle" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Version with bug
6.0.400-preview.22330.6
Last version that worked well
Unknown/Other
Affected platforms
iOS, macOS
Affected platform versions
iOS 15.5, macOS 12
Did you find any workaround?
No workaround found
Relevant log output
System.NullReferenceException: Object reference not set to an instance of an object.
at at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.UnevenListViewDataSource.ClearPrototype()
at at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.UnevenListViewDataSource.InvalidatingPrototypicalCellCache()
at at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.ListViewDataSource.InvalidatePrototypicalCellCache()
at at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.InvalidateCellCache()
at at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.UpdateItems(NotifyCollectionChangedEventArgs e, Int32 section, Boolean resetWhenGrouped)
at at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
at at Microsoft.Maui.Controls.Internals.TemplatedItemsList`2[[Microsoft.Maui.Controls.ItemsView`1[[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at at Microsoft.Maui.Controls.Internals.TemplatedItemsList`2[[Microsoft.Maui.Controls.ItemsView`1[[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnProxyCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
at at Microsoft.Maui.Controls.ListProxy.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at at Microsoft.Maui.Controls.ListProxy.<>c__DisplayClass34_0.<OnCollectionChanged>b__0()
at at Microsoft.Maui.Dispatching.Dispatcher.<>c__DisplayClass9_0.<DispatchImplementation>b__0()
at at CoreFoundation.DispatchQueue.static_dispatcher_to_managed(IntPtr context)
at at UIKit.UIApplication.Main(String[] args, Type principalClass, Type delegateClass)
at DsfrsApp.Program.Main(String[] args) in /Users/gavinbeard/Projects/DsfrsApp/DsfrsApp/Platforms/iOS/Program.cs:13
I see you mention 6.0 Release Candidate 3 specifically as a version, is that correct? What does the command dotnet --version tell you?
Hi @gavinb80. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
I see you mention 6.0 Release Candidate 3 specifically as a version, is that correct? What does the command
dotnet --versiontell you?
Hi
Version is 6.0.400-preview.22330.6 which I believe is the latest
I believe that I am seeing the same issue when displaying a ReadOnlyObservableCollection in a ListView. In my case, the ROOC is exposed by the view model from an underlying DynamicData SourceList that is being filtered and update behind the scenes. The list loads just fine the first time, but I get this NullReferenceException when the view deactivates and the underlying DynamicData subscription is disposed.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.UnevenListViewDataSource.ClearPrototype()
at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.UnevenListViewDataSource.InvalidatingPrototypicalCellCache()
at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.ListViewDataSource.InvalidatePrototypicalCellCache()
at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.InvalidateCellCache()
at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.UpdateItems(NotifyCollectionChangedEventArgs e, Int32 section, Boolean resetWhenGrouped)
at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
at Microsoft.Maui.Controls.Internals.TemplatedItemsList`2[[Microsoft.Maui.Controls.ItemsView`1[[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnCollectionChanged(NotifyCollectionChangedEventArgs e)
at Microsoft.Maui.Controls.Internals.TemplatedItemsList`2[[Microsoft.Maui.Controls.ItemsView`1[[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnProxyCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
at Microsoft.Maui.Controls.Internals.TemplatedItemsList`2[[Microsoft.Maui.Controls.ItemsView`1[[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnItemsSourceChanged(Boolean fromGrouping)
at Microsoft.Maui.Controls.Internals.TemplatedItemsList`2[[Microsoft.Maui.Controls.ItemsView`1[[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Cell, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].BindableOnPropertyChanged(Object sender, PropertyChangedEventArgs e)
at Microsoft.Maui.Controls.BindableObject.OnPropertyChanged(String propertyName)
at Microsoft.Maui.Controls.Element.OnPropertyChanged(String propertyName)
at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
at Microsoft.Maui.Controls.BindingExpression.ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget)
at Microsoft.Maui.Controls.BindingExpression.Apply(Boolean fromTarget)
at Microsoft.Maui.Controls.BindingExpression.BindingExpressionPart.<PropertyChanged>b__49_0()
at Microsoft.Maui.Controls.DispatcherExtensions.DispatchIfRequired(IDispatcher dispatcher, Action action)
at Microsoft.Maui.Controls.BindingExpression.BindingExpressionPart.PropertyChanged(Object sender, PropertyChangedEventArgs args)
Hi @gavinb80. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md
This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
@PureWeen has commented on Discord that this is likely a regression that was previously fixed in Xamarin Forms and related to the following line missing a ? after element. https://github.com/dotnet/maui/blob/64432c450080efa99084f040c933c9011b066989/src/Controls/src/Core/Compatibility/Handlers/ListView/iOS/ListViewRenderer.cs#L964
I'm going to try to find time to do a repro this weekend.
Repo on 6.0.401 on MacOS [edit: still a problem in 7.0.100 rc1] https://github.com/mike3sullivan/MauiListViewHasUnevenRowsItemTemplate
Specifically, use of HasUnevenRows=True in combination with an ItemTemplate.
In Main.xaml.cs, exception caught in Reset_Clicked (ObservableCollection
Still seems to be ab issue in rc2
@gavinb80 RC2 of .NET MAUI hasn't been released yet. It will release with Preview 4
Now resolved with Preview 4