Silverlight:如何制作UIElement的ShallowCopy

时间:2012-11-23 01:10:09

标签: silverlight clone uielement shallow-copy

我需要在两个不同的画布上添加UIElement,但是一个UIElement只能是一个画布的子画面,所以我必须创建一个ShallowCopy(不需要DeepCopy)UIElement 1}}。

我想使用MemberwiseClone,但它受到保护,我无法使用它。

我还想定义一个扩展方法UIElement.ShallowCopy,但它仍然会调用MemberwiseClone,它会再次受到保护。

编辑:

尝试了以下所有方法,但所有这些都在Silverlight环境中失败了:

    // System.Runtime.Serialization.InvalidDataContractException was unhandled by user code
    // Message=Type 'System.Windows.UIElement' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. Alternatively, you can ensure that the type is public and has a parameterless constructor - all public members of the type will then be serialized, and no attributes will be required.
    public static T CloneEx<T>(this T obj) where T : class
    {
        T clone;
        DataContractSerializer dcs = new DataContractSerializer(typeof(T));

        using (MemoryStream ms = new MemoryStream())
        {
            dcs.WriteObject(ms, obj);
            ms.Position = 0;
            clone = (T)dcs.ReadObject(ms);
        }

        return clone;
    }

    // This one also throws Access/Invoke exceptions
    private readonly static object _lock = new object();
    public static T MemberwiseCloneEx<T>(this T obj) where T : class
    {
        if (obj == null)
            return null;

        try
        {
            Monitor.Enter(_lock);

            T clone = (T)Activator.CreateInstance(obj.GetType());

            PropertyInfo[] fields = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            foreach (PropertyInfo field in fields)
            {
                object val = field.GetValue(obj, null);
                field.SetValue(clone, val, null);
            }

            return clone;
        }
        finally
        {
            Monitor.Exit(_lock);
        }
    }

    // System.MethodAccessException was unhandled by user code
    // Message=Attempt by method 'ToonController.ControllerUtils.MemberwiseCloneEx<System.__Canon>(System.__Canon)' to access method 'System.Object.MemberwiseClone()' failed.
    public static T MemberwiseCloneEx<T>(this T obj) where T : class
    {
        if (obj == null)
            return null;

        MethodInfo mi = obj.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

        if (mi == null)
            return null;

        return (T)mi.Invoke(obj, null);
    }

1 个答案:

答案 0 :(得分:1)

如果你想在多个ui元素中使用某些东西,“同步它们”,那么你应该创建一个ViewModel或类似的东西。此视图模型将设置为您要使用它的任何元素的datacontext。然后你的浅引用很简单,你可以创建两个独立的UI元素绑定到相同的数据。