dotnet/maui · error · InvalidOperationException

View for cell must implement {nameof(INativeElementView)} to

Error message

View for cell must implement {nameof(INativeElementView)} to enable recycling.

What it means

ListViewAdapter.GetView, when the ListView uses RecycleElement caching and a convertView is provided (i.e. Android is recycling), requires convertView to implement INativeElementView so it can recover the Cell via boxedCell.Element. If the recycled view is a plain view (e.g. a custom ViewCell whose renderer does not implement INativeElementView), recycling cannot proceed and an InvalidOperationException is thrown.

Source

Thrown at src/Compatibility/Core/src/Android/Renderers/ListViewAdapter.cs:256

			var cellIsBeingReused = false;
			var layout = convertView as Handlers.Compatibility.ConditionalFocusLayout;
			if (layout != null)
			{
				cellIsBeingReused = true;
				convertView = layout.GetChildAt(0);
			}
			else
			{
				layout = new Handlers.Compatibility.ConditionalFocusLayout(_context) { Orientation = Orientation.Vertical };
				_layoutsCreated.Add(layout);
			}

			if (((cachingStrategy & ListViewCachingStrategy.RecycleElement) != 0) && convertView != null)
			{
				var boxedCell = convertView as INativeElementView;
				if (boxedCell == null)
				{
					throw new InvalidOperationException($"View for cell must implement {nameof(INativeElementView)} to enable recycling.");
				}
				cell = (Cell)boxedCell.Element;

				ICellController cellController = cell;
				cellController.SendDisappearing();

				int row = position;
				var group = 0;
				var templatedItems = TemplatedItemsView.TemplatedItems;
				if (_listView.IsGroupingEnabled)
					group = templatedItems.GetGroupIndexFromGlobal(position, out row);

				var templatedList = templatedItems.GetGroup(group);

				if (_listView.IsGroupingEnabled)
				{
					if (row == 0)
						templatedList.UpdateHeader(cell, group);

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Have the custom view/renderer implement INativeElementView (expose Element).
  2. If you cannot implement the interface, switch the ListView to CachingStrategy=RetainElement (at a memory cost).
  3. Use the standard Cell subclasses whose renderers already implement INativeElementView.

Example fix

// before — custom view without the interface
public class MyCustomView : LinearLayout { /* no INativeElementView */ }
// after
public class MyCustomView : LinearLayout, INativeElementView
{
    public Element Element { get; set; }
}
Defensive patterns

Strategy: validation

Validate before calling

if (listView.CachingStrategy == ListViewCachingStrategy.RecycleElement)
{
    foreach (var vc in listView.TemplatedItems)
        if (vc?.View is not null && vc.Renderer is Android.Views.View av && av is not INativeElementView)
            listView.CachingStrategy = ListViewCachingStrategy.RetainElement; // or fix the renderer
}

Type guard

static bool SupportsRecycle(ViewCell cell)
{
    var renderer = Platform.GetRenderer(cell.View);
    return renderer?.GetView?.(cell.View) is INativeElementView; // pseudo
}
// simpler: ensure the custom view class implements INativeElementView

Try / catch

try { /* build ListView */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("INativeElementView"))
{ listView.CachingStrategy = ListViewCachingStrategy.RetainElement; }

Prevention

When it happens

Trigger: ListView with CachingStrategy=RecycleElement whose ViewCell renders a custom view that does not implement INativeElementView, and Android attempts to recycle that view (convertView != null).

Common situations: Custom ViewCell with a renderer returning a native Android view that skips the INativeElementView contract; mixing a hand-rolled cell renderer with RecycleElement; upgrading a RetainElement-style custom cell to a recycled ListView without implementing the interface.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/f0fd955325076e3d. Report an issue: GitHub.