C# 断开元素与WPF中任何/未指定父容器的连接
我有一个控件是另一个控件的子控件(因为所有非根控件/元素都在WPF中)。 如果我想将控件移动到另一个容器中,我必须首先将其与其当前容器断开连接(否则会引发异常) 如果我知道父对象是什么,那么我可以将其从其子对象集合、内容或任何内容中删除。但是,如果我不知道父容器的类型是什么,那么我如何删除子控件呢 在下面的代码示例中:如何将“sp1”移动到另一个容器,而不知道父容器(面板、GroupBox…)的类型 理想情况下,我只想写以下内容:C# 断开元素与WPF中任何/未指定父容器的连接,c#,wpf,logical-tree,C#,Wpf,Logical Tree,我有一个控件是另一个控件的子控件(因为所有非根控件/元素都在WPF中)。 如果我想将控件移动到另一个容器中,我必须首先将其与其当前容器断开连接(否则会引发异常) 如果我知道父对象是什么,那么我可以将其从其子对象集合、内容或任何内容中删除。但是,如果我不知道父容器的类型是什么,那么我如何删除子控件呢 在下面的代码示例中:如何将“sp1”移动到另一个容器,而不知道父容器(面板、GroupBox…)的类型 理想情况下,我只想写以下内容: sp1.Parent.RemoveChild(sp1); 但是
sp1.Parent.RemoveChild(sp1);
但是我还没有找到这样的东西。新:
我建议使用基类而不是列出的所有其他类。试试这段代码,这3个类是最适合您需要的用例。据我所知,这几乎与previos相同(见下)
旧的:
据我所知,您可以使用类型作为父类型,并尝试调用RemoveVisualChild方法 您可以使用扩展方法编写助手类:
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
}
}
@Clemens解决方案的我的版本:
/// <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;
//}
}
//
///断开与其父级的连接(如果有)。
///
///
公共静态无效断开连接(此FrameworkElement子级)
{
var parent=child.parent;
如果(父项==null)
返回;
如果(父面板为面板)
{
面板。儿童。移除(儿童);
返回;
}
if(父项是装饰者装饰者)
{
if(decorator.Child==Child)
decorator.Child=null;
返回;
}
if(父级为ContentPresenter ContentPresenter)
{
if(contentPresenter.Content==子级)
contentPresenter.Content=null;
返回;
}
if(父项为ContentControl ContentControl)
{
if(contentControl.Content==子级)
contentControl.Content=null;
返回;
}
//if(父项为ItemsControl ItemsControl)
//{
//itemsControl.Items.Remove(子项);
//返回;
//}
}
为了完整性,我在ItemsControl检查中添加了一个Add方法,该方法将返回子项。子树或父树可能还不在可视树中,因此您必须同时检查可视树和逻辑树:
/// <summary>
/// Adds or inserts a child back into its parent
/// </summary>
/// <param name="child"></param>
/// <param name="index"></param>
public static void AddToParent(this UIElement child, DependencyObject parent, int? index = null)
{
if (parent == null)
return;
if (parent is ItemsControl itemsControl)
if (index == null)
itemsControl.Items.Add(child);
else
itemsControl.Items.Insert(index.Value, child);
else if (parent is Panel panel)
if (index == null)
panel.Children.Add(child);
else
panel.Children.Insert(index.Value, child);
else if (parent is Decorator decorator)
decorator.Child = child;
else if (parent is ContentPresenter contentPresenter)
contentPresenter.Content = child;
else if (parent is ContentControl contentControl)
contentControl.Content = child;
}
/// <summary>
/// Removes the child from its parent collection or its content.
/// </summary>
/// <param name="child"></param>
/// <param name="parent"></param>
/// <returns></returns>
public static bool RemoveFromParent(this UIElement child, out DependencyObject parent, out int? index)
{
parent = child.GetParent(true);
if (parent == null)
parent = child.GetParent(false);
index = null;
if (parent == null)
return false;
if (parent is ItemsControl itemsControl)
{
if (itemsControl.Items.Contains(child))
{
index = itemsControl.Items.IndexOf(child);
itemsControl.Items.Remove(child);
return true;
}
}
else if (parent is Panel panel)
{
if (panel.Children.Contains(child))
{
index = panel.Children.IndexOf(child);
panel.Children.Remove(child);
return true;
}
}
else if (parent is Decorator decorator)
{
if (decorator.Child == child)
{
decorator.Child = null;
return true;
}
}
else if (parent is ContentPresenter contentPresenter)
{
if (contentPresenter.Content == child)
{
contentPresenter.Content = null;
return true;
}
}
else if (parent is ContentControl contentControl)
{
if (contentControl.Content == child)
{
contentControl.Content = null;
return true;
}
}
return false;
}
public static DependencyObject GetParent(this DependencyObject depObj, bool isVisualTree)
{
if (isVisualTree)
{
if(depObj is Visual || depObj is Visual3D)
return VisualTreeHelper.GetParent(depObj);
return null;
}
else
return LogicalTreeHelper.GetParent(depObj);
}
//
///将子项添加或插入回其父项
///
///
///
公共静态void AddToParent(此UIElement子元素,DependencyObject父元素,int?index=null)
{
如果(父项==null)
返回;
if(父项为ItemsControl ItemsControl)
如果(索引==null)
itemsControl.Items.Add(子项);
其他的
itemsControl.Items.Insert(index.Value,子项);
else if(父级为面板)
如果(索引==null)
panel.Children.Add(child);
其他的
panel.Children.Insert(index.Value,Children);
else if(父项是Decorator Decorator)
decorator.Child=Child;
else if(父项为ContentPresenter ContentPresenter)
contentPresenter.Content=child;
else if(父项为ContentControl ContentControl)
contentControl.Content=child;
}
///
///从其父集合或其内容中删除子集合。
///
///
///
///
public static bool RemoveFromParent(此UIElement子级,out DependencyObject父级,out int?索引)
{
parent=child.GetParent(true);
如果(父项==null)
parent=child.GetParent(false);
索引=空;
如果(父项==null)
返回false;
if(父项为ItemsControl ItemsControl)
{
if(itemsControl.Items.Contains(子项))
{
index=itemsControl.Items.IndexOf(子项);
itemsControl.Items.Remove(子项);
返回true;
}
}
else if(父级为面板)
{
if(panel.Children.Contains(child))
{
索引=panel.Children.IndexOf(child);
面板。儿童。移除(儿童);
返回true;
}
}
else if(父项是Decorator Decorator)
{
if(decorator.Child==Child)
{
decorator.Child=null;
返回true;
}
}
else if(父项为ContentPresenter ContentPresenter)
{
if(contentPresenter.Content==子级)
{
contentPresenter.Content=null;
返回true;
}
}
else if(父项为ContentControl ContentControl)
{
if(contentControl.Content==子级)
{
contentControl.Content=null;
返回true;
}
}
返回false;
}
公共静态DependencyObject GetParent(此DependencyObject depObj,bool为VisualTree)
{
if(isVisualTree)
{
如果(depObj是可视的| | depObj是可视的3D)
返回visualtreeheloper.GetParent(depObj);
返回null;
}
其他的
返回LogicalTreeHelper.GetParent(depObj);
}
RemoveVisualChild on Visual受保护。所以很不幸,我不能称之为它-否则它将是我一直在寻找的。接受!这个答案还有一些有趣的信息:我还添加了ItemsControl:var ItemsControl=parent作为ItemsControl;如果(itemsControl!=null){itemsControl.Items.Remove(child);return;}可以,但要注意itemsControl中的项通常不是UI元素,而是通过数据模板获得UI的数据项。
/// <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;
//}
}
/// <summary>
/// Adds or inserts a child back into its parent
/// </summary>
/// <param name="child"></param>
/// <param name="index"></param>
public static void AddToParent(this UIElement child, DependencyObject parent, int? index = null)
{
if (parent == null)
return;
if (parent is ItemsControl itemsControl)
if (index == null)
itemsControl.Items.Add(child);
else
itemsControl.Items.Insert(index.Value, child);
else if (parent is Panel panel)
if (index == null)
panel.Children.Add(child);
else
panel.Children.Insert(index.Value, child);
else if (parent is Decorator decorator)
decorator.Child = child;
else if (parent is ContentPresenter contentPresenter)
contentPresenter.Content = child;
else if (parent is ContentControl contentControl)
contentControl.Content = child;
}
/// <summary>
/// Removes the child from its parent collection or its content.
/// </summary>
/// <param name="child"></param>
/// <param name="parent"></param>
/// <returns></returns>
public static bool RemoveFromParent(this UIElement child, out DependencyObject parent, out int? index)
{
parent = child.GetParent(true);
if (parent == null)
parent = child.GetParent(false);
index = null;
if (parent == null)
return false;
if (parent is ItemsControl itemsControl)
{
if (itemsControl.Items.Contains(child))
{
index = itemsControl.Items.IndexOf(child);
itemsControl.Items.Remove(child);
return true;
}
}
else if (parent is Panel panel)
{
if (panel.Children.Contains(child))
{
index = panel.Children.IndexOf(child);
panel.Children.Remove(child);
return true;
}
}
else if (parent is Decorator decorator)
{
if (decorator.Child == child)
{
decorator.Child = null;
return true;
}
}
else if (parent is ContentPresenter contentPresenter)
{
if (contentPresenter.Content == child)
{
contentPresenter.Content = null;
return true;
}
}
else if (parent is ContentControl contentControl)
{
if (contentControl.Content == child)
{
contentControl.Content = null;
return true;
}
}
return false;
}
public static DependencyObject GetParent(this DependencyObject depObj, bool isVisualTree)
{
if (isVisualTree)
{
if(depObj is Visual || depObj is Visual3D)
return VisualTreeHelper.GetParent(depObj);
return null;
}
else
return LogicalTreeHelper.GetParent(depObj);
}