{"record":{"id":"831437c59ed367dc","repo":"dotnet/maui","slug":"view-for-cell-must-implement-inativeelementview-to","errorCode":null,"errorMessage":"View for cell must implement INativeElementView to enable recycling.","messagePattern":"View for cell must implement INativeElementView to enable recycling\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Compatibility/Core.LegacyRenderers/Android/ListViewAdapter.cs","lineNumber":255,"sourceCode":"\t\t\tvar cellIsBeingReused = false;\n\t\t\tvar layout = convertView as ConditionalFocusLayout;\n\t\t\tif (layout != null)\n\t\t\t{\n\t\t\t\tcellIsBeingReused = true;\n\t\t\t\tconvertView = layout.GetChildAt(0);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlayout = new ConditionalFocusLayout(_context) { Orientation = Orientation.Vertical };\n\t\t\t\t_layoutsCreated.Add(layout);\n\t\t\t}\n\n\t\t\tif (((cachingStrategy & ListViewCachingStrategy.RecycleElement) != 0) && convertView != null)\n\t\t\t{\n\t\t\t\tvar boxedCell = convertView as INativeElementView;\n\t\t\t\tif (boxedCell == null)\n\t\t\t\t{\n\t\t\t\t\tthrow new InvalidOperationException($\"View for cell must implement {nameof(INativeElementView)} to enable recycling.\");\n\t\t\t\t}\n\t\t\t\tcell = (Cell)boxedCell.Element;\n\n\t\t\t\tICellController cellController = cell;\n\t\t\t\tcellController.SendDisappearing();\n\n\t\t\t\tint row = position;\n\t\t\t\tvar group = 0;\n\t\t\t\tvar templatedItems = TemplatedItemsView.TemplatedItems;\n\t\t\t\tif (_listView.IsGroupingEnabled)\n\t\t\t\t\tgroup = templatedItems.GetGroupIndexFromGlobal(position, out row);\n\n\t\t\t\tvar templatedList = templatedItems.GetGroup(group);\n\n\t\t\t\tif (_listView.IsGroupingEnabled)\n\t\t\t\t{\n\t\t\t\t\tif (row == 0)\n\t\t\t\t\t\ttemplatedList.UpdateHeader(cell, group);","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Compatibility/Core.LegacyRenderers/Android/ListViewAdapter.cs#L237-L273","documentation":"Thrown by the legacy Android ListViewAdapter when ListViewCachingStrategy.RecycleElement is active and the recycled Android convertView cannot be cast to INativeElementView. Cell recycling on Android requires each native cell view to expose its backing Cell via the INativeElementView.Element property so the adapter can rebind data instead of inflating a new view. When the recycled view does not implement this interface, the adapter cannot safely reuse it and aborts.","triggerScenarios":"A ListView is created with CachingStrategy=RecycleElement and a DataTemplate whose cell produces a native view that does not implement INativeElementView. This happens with custom cell renderers that return a plain Android View, or when a third-party/legacy cell renderer bypasses the standard ViewCellContainer (which does implement INativeElementView). It can also surface after a Xamarin.Forms version upgrade that changed internal cell view types.","commonSituations":"Migrating an app from an old Xamarin.Forms version where a custom ViewCell renderer returned a raw ViewGroup. Mixing custom renderers that wrap but do not subclass the framework's cell container. Using RecycleElement with a custom cell type whose renderer was only ever tested under RetainElement.","solutions":["Switch the ListView to CachingStrategy=RetainElement (or omit the strategy) so views are not recycled and the cast is never attempted.","Ensure any custom cell renderer returns a view that implements INativeElementView, or reuse/extend the built-in ViewCellContainer which already implements it.","Migrate the ListView to CollectionView, which uses a modern adapter and does not depend on INativeElementView recycling contracts.","If using a third-party cell renderer, verify it is compatible with RecycleElement; contact the vendor or wrap its output in an INativeElementView-implementing container."],"exampleFix":"// before\nvar listView = new ListView(ListViewCachingStrategy.RecycleElement)\n{\n    ItemTemplate = new DataTemplate(() => new MyCustomCell())\n};\n\n// after (option 1: disable recycling)\nvar listView = new ListView(ListViewCachingStrategy.RetainElement)\n{\n    ItemTemplate = new DataTemplate(() => new MyCustomCell())\n};\n\n// after (option 2: make custom cell view implement INativeElementView)\nclass MyCellView : LinearLayout, INativeElementView\n{\n    public Element Element => _cell;\n}","handlingStrategy":"validation","validationCode":"// Before assigning a DataTemplate with a custom cell to a RecycleElement ListView,\n// verify the cell's native view implements INativeElementView.\nbool CanRecycleCell(Func<Cell> cellFactory)\n{\n    var cell = cellFactory();\n    // For ViewCells the framework wraps in ViewCellContainer (INativeElementView);\n    // custom cells must implement it themselves.\n    var renderer = Platform.GetRenderer(cell.View);\n    return renderer?.View is INativeElementView;\n}","typeGuard":"static bool IsRecyclableCell(Cell cell)\n{\n    if (cell is ViewCell vc && vc.View != null)\n    {\n        var r = Platform.GetRenderer(vc.View);\n        return r?.View is INativeElementView;\n    }\n    return false;\n}","tryCatchPattern":null,"preventionTips":["Prefer CachingStrategy.RetainElement for custom cells unless you have verified INativeElementView support.","Use the built-in ViewCellContainer-based cell hierarchy which already implements INativeElementView.","Migrate to CollectionView which does not depend on the legacy recycling contract.","Write an instrumented test that toggles RecycleElement and scrolls a large list with your custom cell to surface recycling errors early."],"tags":["android","listview","recycling","renderer","xamarin-forms"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}