Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 断开元素与WPF中任何/未指定父容器的连接_C#_Wpf_Logical Tree - Fatal编程技术网

C# 断开元素与WPF中任何/未指定父容器的连接

C# 断开元素与WPF中任何/未指定父容器的连接,c#,wpf,logical-tree,C#,Wpf,Logical Tree,我有一个控件是另一个控件的子控件(因为所有非根控件/元素都在WPF中)。 如果我想将控件移动到另一个容器中,我必须首先将其与其当前容器断开连接(否则会引发异常) 如果我知道父对象是什么,那么我可以将其从其子对象集合、内容或任何内容中删除。但是,如果我不知道父容器的类型是什么,那么我如何删除子控件呢 在下面的代码示例中:如何将“sp1”移动到另一个容器,而不知道父容器(面板、GroupBox…)的类型 理想情况下,我只想写以下内容: sp1.Parent.RemoveChild(sp1); 但是

我有一个控件是另一个控件的子控件(因为所有非根控件/元素都在WPF中)。 如果我想将控件移动到另一个容器中,我必须首先将其与其当前容器断开连接(否则会引发异常)

如果我知道父对象是什么,那么我可以将其从其子对象集合、内容或任何内容中删除。但是,如果我不知道父容器的类型是什么,那么我如何删除子控件呢

在下面的代码示例中:如何将“sp1”移动到另一个容器,而不知道父容器(面板、GroupBox…)的类型

理想情况下,我只想写以下内容:

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);
    }