Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disconnecting an element from any/unspecified parent container in WPF

I have a control that is a child of another control (as all non-root controls/elemts are in WPF). If I want to move the control to another container I have to disconnect it from its current container first (otherwise an exception is thrown).

If I know what the parent is then I can just remove it from its Children collection, or Content or whatever. But what if I don't know what the parent container's type is - how do I remove the child control then?

In the code sample below: How would I be able to move "sp1" to another container without knowing the type of the parent (Panel, GroupBox...)?

// Add the child object "sp1" to a container (of any type).
StackPanel sp1 = new StackPanel();
SomeParentControl.Children.Add(sp1);

// Somewhere else in the code. I still have a reference to "sp1" but now I don't know what container it is in. I just want to move the "sp1" object to another parent container.
AnotherParentControl.Content = sp1; // Generates exception: "Must disconnect specified child from current parent Visual before attaching to new parent Visual."

Ideally I would just like to write something like:

sp1.Parent.RemoveChild(sp1);

But I haven't found anything like that.

like image 346
Björn Avatar asked Oct 11 '13 11:10

Björn


2 Answers

You may write a helper class with an extension method:

public static class RemoveChildHelper
{
    public static void RemoveChild(this DependencyObject parent, UIElement child)
    {
        var panel = parent as Panel;
        if (panel != null)
        {
            panel.Children.Remove(child);
            return;
        }

        var decorator = parent as Decorator;
        if (decorator != null)
        {
            if (decorator.Child == child)
            {
                decorator.Child = null;
            }
            return;
        }

        var contentPresenter = parent as ContentPresenter;
        if (contentPresenter != null)
        {
            if (contentPresenter.Content == child)
            {
                contentPresenter.Content = null;
            }
            return;
        }

        var contentControl = parent as ContentControl;
        if (contentControl != null)
        {
            if (contentControl.Content == child)
            {
                contentControl.Content = null;
            }
            return;
        }

        // maybe more
    }
}
like image 60
Clemens Avatar answered Nov 02 '22 12:11

Clemens


NEW:

I propose to use base classes instead of all other listed. Try this code, this 3 classes are the most use cases for your needs. As I understand, it's almost the same as previos ^)

  var parent = VisualTreeHelper.GetParent(child);
  var parentAsPanel = parent as Panel;
  if (parentAsPanel != null)
  {
      parentAsPanel.Children.Remove(child);
  }
  var parentAsContentControl = parent as ContentControl;
  if (parentAsContentControl != null)
  {
      parentAsContentControl.Content = null;
  }
  var parentAsDecorator = parent as Decorator;
  if (parentAsDecorator != null)
  {
      parentAsDecorator.Child = null;
  }

OLD: As far as I remember, you can use Visual type as parent type and try to call RemoveVisualChild method.

like image 45
Lonli-Lokli Avatar answered Nov 02 '22 10:11

Lonli-Lokli