{"record":{"id":"479045258d4d9b08","repo":"dotnet/maui","slug":"cannot-assign-a-native-control-without-an-element","errorCode":null,"errorMessage":"Cannot assign a native control without an Element; Renderer unbound and/or disposed. Please consult Microsoft.Maui.Controls.Compatibility renderers for reference implementation of OnElementChanged.","messagePattern":"Cannot assign a native control without an Element; Renderer unbound and/or disposed\\. Please consult Microsoft\\.Maui\\.Controls\\.Compatibility renderers for reference implementation of OnElementChanged\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Compatibility/Core/src/Windows/VisualElementRenderer.cs","lineNumber":429,"sourceCode":"\n\t\t\t\toldControl.Loaded -= OnControlLoaded;\n\t\t\t\toldControl.GotFocus -= OnControlGotFocus;\n\t\t\t\toldControl.LostFocus -= OnControlLostFocus;\n\t\t\t}\n\n\t\t\tUpdateTracker();\n\n\t\t\tif (control == null)\n\t\t\t{\n\t\t\t\t_controlChanged?.Invoke(this, EventArgs.Empty);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tControl.HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Stretch;\n\t\t\tControl.VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Stretch;\n\n\t\t\tif (Element == null)\n\t\t\t\tthrow new InvalidOperationException(\n\t\t\t\t\t\"Cannot assign a native control without an Element; Renderer unbound and/or disposed. \" +\n\t\t\t\t\t\"Please consult Microsoft.Maui.Controls.Compatibility renderers for reference implementation of OnElementChanged.\");\n\n\t\t\tElement.IsPlatformStateConsistent = false;\n\t\t\tcontrol.Loaded += OnControlLoaded;\n\n\t\t\tcontrol.GotFocus += OnControlGotFocus;\n\t\t\tcontrol.LostFocus += OnControlLostFocus;\n\n#pragma warning disable RS0030 // Do not use banned APIs; Panel.Children is banned for performance reasons.\n\t\t\tChildren.Add(control);\n#pragma warning restore RS0030 // Do not use banned APIs\n\n\t\t\tUpdateBackgroundColor();\n\t\t\tUpdateBackground();\n\n\t\t\tif (Element != null && !string.IsNullOrEmpty(Element.AutomationId))\n\t\t\t\tSetAutomationId(Element.AutomationId);","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Compatibility/Core/src/Windows/VisualElementRenderer.cs#L411-L447","documentation":"VisualElementRenderer.SetControl (called via SetNativeControl) throws InvalidOperationException when assigning a native control while Element is null. This indicates the renderer is unbound — either disposed, or SetNativeControl was called before SetElement in the lifecycle. The renderer needs an Element to wire up platform-state consistency and event handlers.","triggerScenarios":"Calling SetNativeControl after Dispose has nulled the Element; renderer reuse after disposal; calling SetNativeControl in OnElementChanged before Element is assigned; async race condition where Dispose runs between element binding and control assignment (common in cell recycling).","commonSituations":"Custom renderer calling SetNativeControl in the constructor instead of OnElementChanged; ListView/CollectionView cell recycling reuses disposed renderers; rapid page navigation triggers disposal during async control setup.","solutions":["Guard SetNativeControl: if (Element != null) { SetNativeControl(control); }","Ensure SetNativeControl is called after SetElement — typically inside OnElementChanged after base.SetElement","Check _disposed flag before calling SetNativeControl in async callbacks","Avoid calling SetNativeControl from constructors; defer to OnElementChanged"],"exampleFix":"// before\nprotected override void OnElementChanged(ElementChangedEventArgs<MyView> e)\n{\n    base.OnElementChanged(e);\n    SetNativeControl(new MyNativeControl()); // may throw if Element is null after dispose\n}\n\n// after\nprotected override void OnElementChanged(ElementChangedEventArgs<MyView> e)\n{\n    base.OnElementChanged(e);\n    if (e.NewElement != null && !_disposed && Control == null)\n        SetNativeControl(new MyNativeControl());\n}","handlingStrategy":"validation","validationCode":"// Before calling SetNativeControl, verify Element is bound\nif (Element == null || _disposed)\n    return;\nSetNativeControl(nativeControl);","typeGuard":null,"tryCatchPattern":"try\n{\n    SetNativeControl(control);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"without an Element\"))\n{\n    // Renderer was disposed — abort control assignment\n    // This is a lifecycle race; the renderer should not be reused\n}","preventionTips":["Always call SetNativeControl inside OnElementChanged after base.SetElement assigns Element","Guard with if (Element != null && !_disposed) before SetNativeControl","Never call SetNativeControl from constructors or async continuations without checking Element","Implement proper disposal flags to prevent reuse of disposed renderers"],"tags":["rendering","lifecycle","disposal","winui","race-condition"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}