{"record":{"id":"ffa2d4920ec3fbc9","repo":"dotnet/maui","slug":"viewcell-must-have-a-view-ffa2d4","errorCode":null,"errorMessage":"ViewCell must have a View","messagePattern":"ViewCell must have a View","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ViewCellRenderer.cs","lineNumber":49,"sourceCode":"\n\t\t\tBindableProperty unevenRows = null, rowHeight = null;\n#pragma warning disable CS0618 // Type or member is obsolete\n\t\t\tif (ParentView is TableView)\n\t\t\t{\n\t\t\t\tunevenRows = TableView.HasUnevenRowsProperty;\n\t\t\t\trowHeight = TableView.RowHeightProperty;\n\t\t\t}\n\t\t\telse if (ParentView is ListView)\n\t\t\t{\n\t\t\t\tcell.IsContextActionsLegacyModeEnabled = item.On<PlatformConfiguration.Android>().GetIsContextActionsLegacyModeEnabled();\n\n\t\t\t\tunevenRows = ListView.HasUnevenRowsProperty;\n\t\t\t\trowHeight = ListView.RowHeightProperty;\n\t\t\t}\n#pragma warning restore CS0618 // Type or member is obsolete\n\n\t\t\tif (cell.View == null)\n\t\t\t\tthrow new InvalidOperationException($\"ViewCell must have a {nameof(cell.View)}\");\n\n\t\t\tvar view = (IPlatformViewHandler)cell.View.ToHandler(cell.FindMauiContext());\n\t\t\tcell.View.IsPlatformEnabled = true;\n\n\t\t\t// If the convertView is null we don't want to return the same view, we need to return a new one.\n\t\t\t// We should probably do this for ListView as well\n#pragma warning disable CS0618 // Type or member is obsolete\n\t\t\tif (ParentView is TableView)\n\t\t\t{\n\t\t\t\tview.ToPlatform().RemoveFromParent();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tViewCellContainer c = view.ToPlatform().GetParentOfType<ViewCellContainer>();\n\n\t\t\t\tif (c != null)\n\t\t\t\t\treturn c;\n\t\t\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Controls/src/Core/Compatibility/Handlers/ListView/Android/ViewCellRenderer.cs#L31-L67","documentation":"Thrown by the Android ViewCellRenderer when cell.View is null at render time. A ViewCell must contain a child View to be measured and displayed; rendering proceeds only after confirming the View is set.","triggerScenarios":"Defining a ViewCell in XAML/code without a View child. Setting View to null dynamically. A DataTemplate whose factory returns a ViewCell before View is assigned (e.g. async population not yet complete at measure time).","commonSituations":"Empty <ViewCell/> in XAML. ViewCell where the View is loaded asynchronously/lazily and not set before the list measures. Conditional View assignment that skips the assignment branch.","solutions":["Always set ViewCell.View to a non-null View before the cell is measured (synchronously in the template factory).","Provide a placeholder/loading View as the default and swap content later if needed.","Validate in the DataTemplate factory that the returned cell has a View."],"exampleFix":"// before\nlistView.ItemTemplate = new DataTemplate(() => new ViewCell());\n\n// after\nlistView.ItemTemplate = new DataTemplate(() =>\n{\n    return new ViewCell { View = new Label { Text = \"Loading\" } };\n});","handlingStrategy":"validation","validationCode":"static ViewCell MakeCell() =>\n    new ViewCell { View = new Label { Text = \"Loading\" } };","typeGuard":"static bool HasView(ViewCell c) => c.View is not null;","tryCatchPattern":null,"preventionTips":["Always set ViewCell.View synchronously in the template factory.","Use a placeholder View for async-loaded content.","Validate the cell before it enters measurement."],"tags":["maui","listview","android","viewcell","null"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}