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.
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
}
}
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.
My version for @Clemens solution:
/// <summary>
/// Disconnects <paramref name="child"/> from it's parent if any.
/// </summary>
/// <param name="child"></param>
public static void DisconnectIt(this FrameworkElement child)
{
var parent = child.Parent;
if (parent == null)
return;
if (parent is Panel panel)
{
panel.Children.Remove(child);
return;
}
if (parent is Decorator decorator)
{
if (decorator.Child == child)
decorator.Child = null;
return;
}
if (parent is ContentPresenter contentPresenter)
{
if (contentPresenter.Content == child)
contentPresenter.Content = null;
return;
}
if (parent is ContentControl contentControl)
{
if (contentControl.Content == child)
contentControl.Content = null;
return;
}
//if (parent is ItemsControl itemsControl)
//{
// itemsControl.Items.Remove(child);
// return;
//}
}
来源:https://stackoverflow.com/questions/19317064/disconnecting-an-element-from-any-unspecified-parent-container-in-wpf