Skip to content

Setting Content of ContentView through style would crash on parent change #11812

@rbakhshi

Description

@rbakhshi

Description

(It was hard to explain in the title)

We have an application with inbuilt navigation structure that runs in Xamarin with no problem but after porting to MAUI it failed on navigating to a new page.

The error on Android is:

Java.Lang.IllegalStateException: 'The specified child already has a parent. You must call removeView() on the child's parent first.'

Imagine the below structure (Sample reproduction solution provided):

<ContentPage>
   <ContentView> <!--Navigation root content holder-->
      <!--Anything here is basically dynamically attached to page through navigation infrastructure.
            Other UI elements work fine but this element here fails-->
      <ContentView Style={SubContent}></ContentView> 
    </ContentView>
</ContentPage>

The problems seems to be that when content is changing, the inner ContentView elements that have their content set through style would somehow be shared (possibly because static styles are singleton) and that causes the next (incoming) content to try to re-attach the same Content generated by style to the page which then throws the exception.

Steps to Reproduce

  1. open the example solution
  2. Run it on Android emulator (What I tested with was Pixel C Api 32)
  3. Click the button which says Clicked 0 times

Link to public reproduction project repository

https://github.com/rbakhshi/bugreporting

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

Android Api 32

Did you find any workaround?

Not yet

Relevant log output

Java.Lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
   at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod(JniObjectReference instance, JniObjectReference type, JniMethodInfo method, JniArgumentValue* args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.g.cs:line 12324
   at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:line 35
   at Android.Views.ViewGroup.AddView(View child) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net6.0/android-31/mcw/Android.Views.ViewGroup.cs:line 1999
   at Microsoft.Maui.Handlers.ContentViewHandler.UpdateContent(IContentViewHandler handler) in D:\a\_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 44
   at Microsoft.Maui.Handlers.ContentViewHandler.MapContent(IContentViewHandler handler, IContentView page) in D:\a\_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 49
   at Microsoft.Maui.PropertyMapper`2.<>c__DisplayClass5_0[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.IContentViewHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 183
   at Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 47
   at Microsoft.Maui.PropertyMapper.UpdateProperties(IElementHandler viewHandler, IElement virtualView) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 82
   at Microsoft.Maui.Handlers.ElementHandler.SetVirtualView(IElement view) in D:\a\_work\1\s\src\Core\src\Handlers\Element\ElementHandler.cs:line 74
   at Microsoft.Maui.Handlers.ViewHandler.SetVirtualView(IElement element) in D:\a\_work\1\s\src\Core\src\Handlers\View\ViewHandler.cs:line 125
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.ContentViewGroup, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IView view) in D:\a\_work\1\s\src\Core\src\Handlers\View\ViewHandlerOfT.cs:line 53
   at Microsoft.Maui.Handlers.ContentViewHandler.SetVirtualView(IView view) in D:\a\_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 27
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.ContentViewGroup, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IElement view) in D:\a\_work\1\s\src\Core\src\Handlers\View\ViewHandlerOfT.cs:line 56
   at Microsoft.Maui.Controls.Element.SetHandler(IElementHandler newHandler) in D:\a\_work\1\s\src\Controls\src\Core\HandlerImpl\Element\Element.Impl.cs:line 64
   at Microsoft.Maui.Controls.Element.set_Handler(IElementHandler value) in D:\a\_work\1\s\src\Controls\src\Core\HandlerImpl\Element\Element.Impl.cs:line 20
   at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IElement.set_Handler(IElementHandler value) in D:\a\_work\1\s\src\Controls\src\Core\HandlerImpl\VisualElement\VisualElement.Impl.cs:line 301
   at Microsoft.Maui.Platform.ElementExtensions.ToHandler(IElement view, IMauiContext context) in D:\a\_work\1\s\src\Core\src\Platform\ElementExtensions.cs:line 96
   at Microsoft.Maui.Platform.ElementExtensions.ToPlatform(IElement view, IMauiContext context) in D:\a\_work\1\s\src\Core\src\Platform\ElementExtensions.cs:line 127
   at Microsoft.Maui.Handlers.ContentViewHandler.UpdateContent(IContentViewHandler handler) in D:\a\_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 44
   at Microsoft.Maui.Handlers.ContentViewHandler.MapContent(IContentViewHandler handler, IContentView page) in D:\a\_work\1\s\src\Core\src\Handlers\ContentView\ContentViewHandler.Android.cs:line 49
   at Microsoft.Maui.PropertyMapper`2.<>c__DisplayClass5_0[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.IContentViewHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 183
   at Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 47
   at Microsoft.Maui.PropertyMapper.UpdateProperty(IElementHandler viewHandler, IElement virtualView, String property) in D:\a\_work\1\s\src\Core\src\PropertyMapper.cs:line 72
   at Microsoft.Maui.Handlers.ElementHandler.UpdateValue(String property) in D:\a\_work\1\s\src\Core\src\Handlers\Element\ElementHandler.cs:line 82
   at Microsoft.Maui.Controls.Element.OnPropertyChanged(String propertyName) in D:\a\_work\1\s\src\Controls\src\Core\Element.cs:line 383
   at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 530
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 466
   at Microsoft.Maui.Controls.BindingExpression.ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget) in D:\a\_work\1\s\src\Controls\src\Core\BindingExpression.cs:line 160
   at Microsoft.Maui.Controls.BindingExpression.Apply(Boolean fromTarget) in D:\a\_work\1\s\src\Controls\src\Core\BindingExpression.cs:line 56
   at Microsoft.Maui.Controls.BindingExpression.BindingExpressionPart.<PropertyChanged>b__49_0() in D:\a\_work\1\s\src\Controls\src\Core\BindingExpression.cs:line 750
   at Microsoft.Maui.Controls.DispatcherExtensions.DispatchIfRequired(IDispatcher dispatcher, Action action) in D:\a\_work\1\s\src\Controls\src\Core\DispatcherExtensions.cs:line 53
   at Microsoft.Maui.Controls.BindingExpression.BindingExpressionPart.PropertyChanged(Object sender, PropertyChangedEventArgs args) in D:\a\_work\1\s\src\Controls\src\Core\BindingExpression.cs:line 750
   at Microsoft.Maui.Controls.BindingExpression.WeakPropertyChangedProxy.OnPropertyChanged(Object sender, PropertyChangedEventArgs e) in D:\a\_work\1\s\src\Controls\src\Core\BindingExpression.cs:line 653
   at MauiAppNew.Library.ClickViewModel.OnPropertyChanged(String propertyName) in C:\workspace\net\bugreporting\ClassLibrary1\ClickViewModel.cs:line 61
   at MauiAppNew.Library.ClickViewModel.set_Count(Int32 value) in C:\workspace\net\bugreporting\ClassLibrary1\ClickViewModel.cs:line 39
   at MauiAppNew.Library.ClickViewModel.<.ctor>b__2_0() in C:\workspace\net\bugreporting\ClassLibrary1\ClickViewModel.cs:line 23
   at Microsoft.Maui.Controls.Command.<>c__DisplayClass4_0.<.ctor>b__0(Object o) in D:\a\_work\1\s\src\Controls\src\Core\Command.cs:line 80
   at Microsoft.Maui.Controls.Command.Execute(Object parameter) in D:\a\_work\1\s\src\Controls\src\Core\Command.cs:line 122
   at Microsoft.Maui.Controls.ButtonElement.ElementClicked(VisualElement visualElement, IButtonElement ButtonElementManager) in D:\a\_work\1\s\src\Controls\src\Core\ButtonElement.cs:line 60
   at Microsoft.Maui.Controls.Button.SendClicked() in D:\a\_work\1\s\src\Controls\src\Core\Button.cs:line 179
   at Microsoft.Maui.Controls.Button.Microsoft.Maui.IButton.Clicked() in D:\a\_work\1\s\src\Controls\src\Core\HandlerImpl\Button\Button.Impl.cs:line 23
   at Microsoft.Maui.Handlers.ButtonHandler.OnClick(IButton button, View v) in D:\a\_work\1\s\src\Core\src\Handlers\Button\ButtonHandler.Android.cs:line 197
   at Microsoft.Maui.Handlers.ButtonHandler.ButtonClickListener.OnClick(View v) in D:\a\_work\1\s\src\Core\src\Handlers\Button\ButtonHandler.Android.cs:line 212
   at Android.Views.View.IOnClickListenerInvoker.n_OnClick_Landroid_view_View_(IntPtr jnienv, IntPtr native__this, IntPtr native_v) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net6.0/android-31/mcw/Android.Views.View.cs:line 2280
   at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V(_JniMarshal_PPL_V callback, IntPtr jnienv, IntPtr klazz, IntPtr p0) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 121
  --- End of managed Java.Lang.IllegalStateException stack trace ---
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
	at android.view.ViewGroup.addViewInner(ViewGroup.java:5247)
	at android.view.ViewGroup.addView(ViewGroup.java:5076)
	at android.view.ViewGroup.addView(ViewGroup.java:5016)
	at android.view.ViewGroup.addView(ViewGroup.java:4988)
	at crc64fcf28c0e24b4cc31.ButtonHandler_ButtonClickListener.n_onClick(Native Method)
	at crc64fcf28c0e24b4cc31.ButtonHandler_ButtonClickListener.onClick(ButtonHandler_ButtonClickListener.java:30)
	at android.view.View.performClick(View.java:7455)
	at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1194)
	at android.view.View.performClickInternal(View.java:7432)
	at android.view.View.access$3700(View.java:835)
	at android.view.View$PerformClick.run(View.java:28810)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7842)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

  --- End of managed Java.Lang.IllegalStateException stack trace ---
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
	at android.view.ViewGroup.addViewInner(ViewGroup.java:5247)
	at android.view.ViewGroup.addView(ViewGroup.java:5076)
	at android.view.ViewGroup.addView(ViewGroup.java:5016)
	at android.view.ViewGroup.addView(ViewGroup.java:4988)
	at crc64fcf28c0e24b4cc31.ButtonHandler_ButtonClickListener.n_onClick(Native Method)
	at crc64fcf28c0e24b4cc31.ButtonHandler_ButtonClickListener.onClick(ButtonHandler_ButtonClickListener.java:30)
	at android.view.View.performClick(View.java:7455)
	at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1194)
	at android.view.View.performClickInternal(View.java:7432)
	at android.view.View.access$3700(View.java:835)
	at android.view.View$PerformClick.run(View.java:28810)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7842)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Workaround

You can use ControlTemplate instead of directly setting Content in style:

Change to the XAML of SubContent

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiAppNew.SubContent"
             ControlTemplate="{StaticResource SubContentTemplate}">
            <!--- removed the style from line above and replaced it with `ControlTemplate` -->
</ContentView>

The control template

    <ControlTemplate x:Key="SubContentTemplate">
        <Label>
            <Label.FormattedText>
                <FormattedString>
                    <Span>SubContent 2</Span>
                    <Span Text="{Binding BindingContext.Text, Source={RelativeSource FindAncestor, AncestorType={Type ContentView}}}"/>
                </FormattedString>
            </Label.FormattedText>
        </Label>
    </ControlTemplate>

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-layoutStackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenterpartner/syncfusionIssues / PR's with Syncfusion collaborationplatform/androids/triagedIssue has been revieweds/verifiedVerified / Reproducible Issue ready for Engineering Triaget/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions