C# 资源字典中的元素是否已经是另一个元素的子元素?

C# 资源字典中的元素是否已经是另一个元素的子元素?,c#,xaml,uwp-xaml,C#,Xaml,Uwp Xaml,在UWP应用程序中,目标为10240;我知道当您尝试添加已在收到的UI中绘制的元素时: 元素已经是另一个元素的子元素。' 但是,我在页面的资源中有一个边框,通过代码添加它,并收到相同的异常 <Page x:Class="App13.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

在UWP应用程序中,目标为10240;我知道当您尝试添加已在收到的UI中绘制的元素时:

元素已经是另一个元素的子元素。'

但是,我在页面的资源中有一个边框,通过代码添加它,并收到相同的异常

<Page
x:Class="App13.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>
    <Border Width="100" Height="100" Background="Red" x:Name="Border" x:Key="Border" />        
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Button Height="100" Width="100" Content="Add" Tapped="Button_Tapped"/>
</Grid>
如果元素在资源字典中,但尚未呈现,它怎么可能是另一个元素的子元素

元素已经是另一个元素的子元素。'

UWP中的每个UI元素一次只能在UI中的一个位置使用。加载资源时将生成实例。因此,您无法再将它们添加到面板中。但是,您可以通过follow
UIElementExtensions
创建深度副本,并将副本添加到面板中

public static class UIElementExtensions
{
    public static T DeepClone<T>(this T source) where T : UIElement
    {

        T result;

        // Get the type
        Type type = source.GetType();

        // Create an instance
        result = Activator.CreateInstance(type) as T;

        CopyProperties<T>(source, result, type);

        DeepCopyChildren<T>(source, result);

        return result;
    }
    private static void DeepCopyChildren<T>(T source, T result) where T : UIElement
    {
        // Deep copy children.
        Panel sourcePanel = source as Panel;
        if (sourcePanel != null)
        {
            Panel resultPanel = result as Panel;
            if (resultPanel != null)
            {
                foreach (UIElement child in sourcePanel.Children)
                {
                    // RECURSION!
                    UIElement childClone = DeepClone(child);
                    resultPanel.Children.Add(childClone);
                }
            }
        }
    }
    private static void CopyProperties<T>(T source, T result, Type type) where T : UIElement
    {
        // Copy all properties.

        IEnumerable<PropertyInfo> properties = type.GetRuntimeProperties();

        foreach (var property in properties)
        {
            if (property.Name != "Name") 
            {
                if ((property.CanWrite) && (property.CanRead))
                {
                    object sourceProperty = property.GetValue(source);

                    UIElement element = sourceProperty as UIElement;
                    if (element != null)
                    {
                        UIElement propertyClone = element.DeepClone();

                        property.SetValue(result, propertyClone);
                    }
                    else
                    {
                        try
                        {
                            property.SetValue(result, sourceProperty);
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine(ex);
                        }
                    }
                }
            }
        }
    }
}
公共静态类UIElementExtensions
{
公共静态T DeepClone(此T源),其中T:UIElement
{
T结果;
//获取类型
Type Type=source.GetType();
//创建一个实例
结果=Activator.CreateInstance(类型)作为T;
CopyProperties(源、结果、类型);
DeepCopyChildren(来源、结果);
返回结果;
}
私有静态void DeepCopyChildren(T source,T result),其中T:UIElement
{
//深度复制儿童。
Panel sourcePanel=源作为面板;
if(sourcePanel!=null)
{
面板结果面板=作为面板的结果;
if(resultPanel!=null)
{
foreach(sourcePanel.Children中的UIElement子元素)
{
//递归!
UIElement childClone=深度克隆(子级);
resultPanel.Children.Add(childClone);
}
}
}
}
私有静态void CopyProperties(T源、T结果、类型),其中T:UIElement
{
//复制所有属性。
IEnumerable properties=type.GetRuntimeProperties();
foreach(属性中的var属性)
{
如果(property.Name!=“Name”)
{
if((property.CanWrite)和&(property.CanRead))
{
对象sourceProperty=property.GetValue(源);
UIElement=sourceProperty作为UIElement;
if(元素!=null)
{
UIElement PropertyCyclone=element.DeepClone();
SetValue(结果,PropertyCyclone);
}
其他的
{
尝试
{
SetValue(结果,sourceProperty);
}
捕获(例外情况除外)
{
系统.诊断.调试.写线(ex);
}
}
}
}
}
}
}
用法

private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
    var border = Resources["Border"] as Border;
    if (!(Content is Panel panel)) return;
    var NewBorder = border.DeepClone<Border>();
    panel.Children.Add(NewBorder);

}
private void按钮\u点击(对象发送器,点击RoutedEventArgs e)
{
var border=资源[“border”]作为边界;
如果(!(内容为面板))返回;
var NewBorder=border.DeepClone();
panel.Children.Add(新订单);
}

异常没有显示太多。只有那个例外。我检查了添加边框的父对象的子对象,除了触发点击事件的按钮之外什么都没有。我检查了,并且在border对象中将父对象设置为null。这是一个小示例。实际上,我在资源字典中有一些带有x:bind的usercontrols。我有一个非常具体的问题,这可以帮助meHi Nico,谢谢你的回答,但我认为资源字典中的资源没有呈现,我认为只有当你试图添加一个已经在UI树中的元素时才会发生异常。
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
    var border = Resources["Border"] as Border;
    if (!(Content is Panel panel)) return;
    var NewBorder = border.DeepClone<Border>();
    panel.Children.Add(NewBorder);

}