Skip to content

[Android] CollectionView: VirtualView cannot be null here, when clearing and adding items on second navigation #12219

@jaldinger

Description

@jaldinger

Description

An Exception occurs when adding item to ObservableCollection with an EmptyView after having navigated to the same page for a second time.

System.InvalidOperationException: 'VirtualView cannot be null here'

The exception occurs:

  • Only on Android (works fine on Windows)
  • Only when navigating to the page a second (or third...) time
  • I tried using VS 17.4.3, as well as 17.5.0 Preview 2.0, both latest as of today
    maui-android 7.0.52/7.0.100 VS 17.4.33205.214, VS 17.5.33209.295
  • Using both CollectionView EmptyView="something" as well as using separate <CollectionView.EmptyView><ContentView>...

Steps to Reproduce

  1. Create a File > New .NET MAUI App
  2. Add a second ContentPage to the project, named "Page2"
  3. In AppShell.xaml.cs add: Routing.RegisterRoute("Page2", typeof(Page2));
  4. In MauiProgram.cs add: builder.Services.AddScoped<Page2>();
  5. In Page2.xaml remove the Label and replace with:
<CollectionView ItemsSource="{Binding Values}">
            
    <CollectionView.EmptyView>
        <ContentView>
            <Label Text="No items"
                    FontAttributes="Bold" />
        </ContentView>
    </CollectionView.EmptyView>
            
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="x:String">
            <Label Text="{Binding .}" />
        </DataTemplate>
    </CollectionView.ItemTemplate>
            
</CollectionView>

<Button
    Text="Load items"
    Pressed="Button_Pressed" />
  1. In Page2.xaml.cs replace the class with:
public partial class Page2 : ContentPage
{
	public ObservableCollection<string> Values { get; set; } = new();

	public Page2()
	{
		InitializeComponent();

		this.BindingContext = this;
	}

	private async void Button_Pressed(object sender, EventArgs e)
	{
		Values.Clear();

		await Task.Delay(1000);

		for (int i = 1; i <= 5; i++)
			Values.Add($"Item #{i}");
	}
}
  1. In MainPage.xaml.cs modify OnCounterClicked as follows:
private async void OnCounterClicked(object sender, EventArgs e)
{
	count++;

	if (count == 1)
		CounterBtn.Text = $"Clicked {count} time";
	else
		CounterBtn.Text = $"Clicked {count} times";

	SemanticScreenReader.Announce(CounterBtn.Text);

    await Shell.Current.GoToAsync("/Page2");
}
  1. Run the app on Android
  2. Click the button on MainPage
  3. Click the button on Page2 two or more times --> works fine
  4. Go back to MainPage
  5. Click the button on MainPage again
  6. Click the button on Page2 --> Exception occurrs:
System.InvalidOperationException: VirtualView cannot be null here    at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[AndroidX.RecyclerView.Widget.RecyclerView, Xamarin.AndroidX.RecyclerView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].get_VirtualView() in D:\a\_work\1\s\src\Core\src\Handlers\View\ViewHandlerOfT.cs:line 42    at Microsoft.Maui.Controls.Handlers.Items.StructuredItemsViewHandler`1[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetItemsLayout() in D:\a\_work\1\s\src\Controls\src\Core\Handlers\Items\StructuredItemsViewHandler.Android.cs:line 10    at Microsoft.Maui.Controls.Handlers.Items.MauiRecyclerView`3[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Handlers.Items.GroupableItemsViewAdapter`2[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Handlers.Items.IGroupableItemsViewSource, 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.Handlers.Items.IGroupableItemsViewSource, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].UpdateLayoutManager() in D:\a\_work\1\s\src\Controls\src\Core\Handlers\Items\Android\MauiRecyclerView.cs:line 288    at Microsoft.Maui.Controls.Handlers.Items.MauiRecyclerView`3[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Handlers.Items.GroupableItemsViewAdapter`2[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Controls.Handlers.Items.IGroupableItemsViewSource, 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.Handlers.Items.IGroupableItemsViewSource, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].UpdateEmptyViewVisibility() in D:\a\_work\1\s\src\Controls\src\Core\Handlers\Items\Android\MauiRecyclerView.cs:line 552    at Microsoft.Maui.Controls.Handlers.Items.DataChangeObserver.OnItemRangeInserted(Int32 positionStart, Int32 itemCount) in D:\a\_work\1\s\src\Controls\src\Core\Handlers\Items\Android\DataChangeObserver.cs:line 53    at AndroidX.RecyclerView.Widget.RecyclerView.AdapterDataObserver.n_OnItemRangeInserted_II(IntPtr jnienv, IntPtr native__this, Int32 positionStart, Int32 itemCount) in C:\a\_work\3\s\generated\androidx.recyclerview.recyclerview\obj\Release\net6.0-android\generated\src\AndroidX.RecyclerView.Widget.RecyclerView.cs:line 1124    at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPII_V(_JniMarshal_PPII_V callback, IntPtr jnienv, IntPtr klazz, Int32 p0, Int32 p1) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 154

Link to public reproduction project repository

https://github.com/jaldinger/MauiAppRepro1.App

Version with bug

7.0

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android (tested 8.1)

Did you find any workaround?

Removing the EmptyView from the CollectionView avoids the exception (but removes the EmtpyView).

Relevant log output

No response

Metadata

Metadata

Assignees

Labels

area-controls-collectionviewCollectionView, CarouselView, IndicatorViewfixed-in-8.0.0-preview.1.7762Look for this fix in 8.0.0-preview.1.7762!p/1Work that is important, and has been scheduled for release in this or an upcoming sprintplatform/androidt/bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions