Tuesday, January 29, 2013

WPF Error : Specified element is already the logical child of another element. Disconnect it first.

When I added a user control onto a window from within code, after I closed that window and instantiated a new instance of the window and tried to add the same user control there, I got the  following error:

Specified element is already the logical child of another element. Disconnect it first.


Even though I tried to set the content property of that window to null (which I set initially to that user control), I still got the above error. Seems like as the error indicates, it wants us to remove the logical child (in this case the user control) first before we can add this user control to another window. (I was under the impression once the window is closed its logical and visual tree would also be destroyed, well that is another investigation I need to do later, but this is wpf and surprises never seem to end!).  So setting to null or resetting does not work.


Seems like method RemoveLogicalChild is the method to use to disconnect this child. However sadly RemoveLogicalChild is only a protected method in base class, therefore we cannot really call it from outside, i.e we cannot call like mywindow.RemoveLogicalChild (though that would be nice!!).

So here is my work around and it worked for me.

I was initially doing -



Window popupView = new Window();
popupView.Content = PopupUserControl; 


within "Closed" event handler I was doing this, which did not work

popupView.Content = null // did not work, still got the same error


Also I could not call the following method from outside like the line below

            popupView.RemoveLogicalChild(..   // NOT THERE


Therefore here is the solution

Made a PopupWindow class inherited from Window class and within which protected method RemoveLogicalChild is accessible.




public partial class PopupWindow : Window
    {
        public PopupWindow()
        {
            InitializeComponent();
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            this.RemoveLogicalChild(this.Content);    // since protected method
        }
    }



and when I am using this PopupWindow, I am just setting the content to user control there.



PopupWindow popupView = new PopupWindow();
       popupView.Content = PopupUserControl;
       popupView.ShowDialog();


This time it works by the fact the RemoveLogicalChild is being executed from within PopupWindow (my own class that I have inherited from window class).




[NOTE: If there is a more straight forward solution, I'ld like to hear, please feel free to post a link]