如何在WinRT XAML c#中克隆元素

本文关键字:元素 XAML WinRT | 更新日期: 2023-09-27 18:05:29

我已经尝试了这种方法,但得到错误"元素已经是另一个元素的子"

var objClone = new MyImageControl();
objClone = this;
((Canvas)this.Parent).Children.Add(objClone);

然后我检查了这个和这个,但是XamlWriter和XamlReader在WinRT中不可用。我曾尝试使用MemberwiseClone(),但它抛出异常,"COM对象已从其底层RCW分离不能使用。System.Runtime.InteropServices.InvalidComObjectException"。所以谁能告诉我如何克隆现有的UserControl在我的画布本身?

如何在WinRT XAML c#中克隆元素

我已经编写了一个UIElement扩展,它复制元素的属性和子元素——注意,它而不是为克隆设置事件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using System.Reflection;
using Windows.UI.Xaml.Controls;
namespace UIElementClone
{
    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") // do not copy names or we cannot add the clone to the same parent as the original.
                {
                    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);
                            }
                        }
                    }
                }
            }
        }        
    }
}

如果你觉得这段代码有用,可以随意使用。

您可以尝试除XamlWriter和XamlReader以外的序列化器来实现您的链接所描述的相同效果。例如,使用ServiceStack。文本到JSON将对象序列化为字符串,然后从该字符串中获取新对象并将其添加到父对象中。