asz
Topic Author
Posts: 1
Joined: 28 Sep 2021, 23:44

Assertion when removing an object from its parent's children collection

29 Sep 2021, 00:20

I have a view with some basic controls. I want to have 2 versions of it so I can do a staged rollout with A/B testing. Version A throws a bunch of controls in a stack panel, and Version B organizes the same set of controls into a slightly different tree structure. My XAML file defines all of the controls using Version A and stubs out some empty containers that Version B uses. Once my page is loaded, I run some code which determines if we are showing A or B. For A, it will remove the Version B stub containers and for B it will remove the controls from the Version A stack panel and add them to the Version B containers (then remove the Version A stack panel entirely). I like this approach because I only need to define the controls 1 time in XAML and can put them in correct place + remove the excess containers for the other version at run-time. Below is the function I'm using for these 2 operations. The problem is that if I call TryFindAndChangeParent with a nullptr newParent (i.e., without adding it back), I get the following assertion failure when the function returns and the control (now with a ref-count of 0) is disposed of:

[NOESIS/E] Assertion failed: mTemplatedParent == 0, at FrameworkElement.cpp(1575)
    static bool TryFindAndChangeParent(FrameworkElement * root, const char * name, Panel * newParent)
    {
        if (!root)
            return false;

        Ptr<FrameworkElement> found(DynamicCast<FrameworkElement*>(root->FindName(name)));

        if (!found)
            return false;

        Ptr<Panel> parent(DynamicCast<Panel*>(found->GetParent()));
        if (!parent)
            return false;

        bool success = parent->GetChildren()->Remove(found);
        if (success && newParent)
        {
            newParent->GetChildren()->Add(found);
        }

        return success;
    }

    static bool TryFindAndRemove(FrameworkElement * root, const char * name)
    {
        return TryFindAndChangeParent(root, name, nullptr);
    }
FWIW all the controls I'm passing to these functions are inside a template and the code is running during the "Loaded" event for that ControlTemplate. I am aware that I could also use collapsed visibility to "remove" an item, but since these controls are meant for an entirely different version of the UI screen, I think it makes more sense to actually remove them.

Also, the C# equivalent of this code works without issue if I run it in Microsoft Blend.

Here is the callstack:

Image
 
User avatar
sfernandez
Site Admin
Posts: 2983
Joined: 22 Dec 2011, 19:20

Re: Assertion when removing an object from its parent's children collection

30 Sep 2021, 10:53

Thanks for reporting this. Our code was not designed to remove elements manually from the template tree, only for applying and removing the whole template. Could you please add a ticket in our bugtracker and we will solve it for the next release?

In the meantime you can just call found->SetTemplatedParent(0,0) to avoid the assert.

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 24 guests