【问题标题】:Element in a resource dictionary is already the child of another element?资源字典中的元素已经是另一个元素的子元素?
【发布时间】:2018-10-10 10:20:14
【问题描述】:

在针对 10240 的 UWP 应用中;我知道当您尝试添加已在 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>

using Windows.UI.Xaml.Input;

namespace App13
{ 
    public sealed partial class MainPage : Page
    {
        public MainPage() => InitializeComponent();

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

            panel.Children.Add(border);
        }
    }
}

如果元素在资源字典中,但尚未渲染,它怎么可能是另一个元素的子元素?

【问题讨论】:

  • 异常没有显示太多。只有那个例外。我检查了要添加边框的父级的子级,除了触发点击事件的按钮之外什么都没有
  • 我查了一下,边框对象中的Parent设置为null
  • 这是一个小例子。实际上,我在资源字典中有一些带有 x:bind 的用户控件。我有一个非常具体的问题,这可以帮助我

标签: c# xaml uwp-xaml


【解决方案1】:

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

UWP 中的每个 UI 元素一次只能在 UI 中的一个位置使用。加载资源时将生成实例。因此,您不能再将它们添加到面板中。不过,您可以通过关注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);
                        }
                    }
                }
            }
        }
    }
}

用法

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

}

【讨论】:

  • 嗨 Nico,感谢您的回答,但我没有呈现资源字典中的资源,我认为只有在您尝试添加 UI 树中已经存在的元素时才会发生异常。跨度>
猜你喜欢
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-02
  • 1970-01-01
相关资源
最近更新 更多