簡體   English   中英

如何在WinRT XAML C#中克隆UIElement?

[英]How to clone UIElement in WinRT XAML C#?

我首先嘗試了這種方法,但得到錯誤“元素已經是另一個元素的孩子”

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

然后我檢查這個這個 ,但的XamlWriter和XamlReader不可在WinRT中。 我試圖使用MemberwiseClone()但它拋出異常,“不能使用已與其底層RCW分離的COM對象System.Runtime.InteropServices.InvalidComObjectException ”。 那么有誰能告訴我如何將畫布中的現有UserControl克隆到自身?

我已經寫了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.Text將JSON序列化為字符串,然后從該字符串中獲取新對象並將其添加到父對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM