Silverlight: How to Make a ShallowCopy of a UIElement

我怕爱的太早我们不能终老 提交于 2019-12-08 04:24:02

问题


I need to add a UIElement to two different canvases, but one UIElement can only be a child of ONE canvas, so I have to create a ShallowCopy (DeepCopy not needed) of the UIElement.

I want to use MemberwiseClone, but it's protected, I cannot use it.

I also want to define an extension method UIElement.ShallowCopy, but it sill still call MemberwiseClone, which is protected again.

EDIT:

Tried all the following, but all of them failed in Silverlight environment:

    // 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:


if you have something that you want to use in multiple ui elements, 'sync them up' then you should create a ViewModel or something similar. This viewmodel would be set to the datacontext of any element you want to use it. Then your shallow reference is simple and you can just create two independent UI elements binding to the same data.



来源:https://stackoverflow.com/questions/13522001/silverlight-how-to-make-a-shallowcopy-of-a-uielement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!