克隆WPF控件和对象层次结构

时间:2011-07-20 18:38:24

标签: c# wpf clone deep-copy

我在克隆对象时遇到了一些问题。它是用于建模应用程序的工具包,工具箱包含类实例作为原型。但是我很难克隆这些:)

以下代码显示了问题:

public abstract class Shape {
  protected List<UIElement> elements;
  private Canvas canvas;
  ...
  public Canvas getCanvas() { ... };
}

public class MovableShape : Shape {
  protected ... propertyA;
  private ... propertyXY;
  ...
}

public abstract class AbstractLayout : MovableShape, ... {
  ...
}

public class SomeLayoutClass : AbstractLayout, ... {
  ...
}

public class AContainingClass {
  SomeLayoutClass Layout { get; set; }
  ...
}

当我将AContainingClass的对象插入到我的项目工作表中时,应该克隆它。到目前为止,我尝试了手动克隆(由于基类中的private字段而失败)和二进制序列化(BinaryFormatterMemoryStreams)。

第一种方法缺少调用base.clone()方法的方法(或者我错了?),后者不起作用,因为UIElement不是[Serializable]

注意:它必须是深拷贝!

有什么想法吗?谢谢!

<小时/> UPDATE

只是为了澄清我的手动克隆方法: 如果每个类都有自己的Clone方法,那么如何调用基类的Clone方法?

public class Shape { // not abstract any more
  ...
  public Shape Clone() {
    Shape clone = new Shape() { PropertyA = this.PropertyA, ... };
    ...do some XamlWriter things to clone UIElements...
    return clone;
  }
}

public class MovableShape : Shape {
  ...
  public MovableShape Clone() {
     // how to call base.Clone??? 
     // this would be required because I have no access to the private fields!
  }
}

3 个答案:

答案 0 :(得分:6)

这里有它的功能:

    public T XamlClone<T>(T source)
    {
        string savedObject = System.Windows.Markup.XamlWriter.Save(source);

        // Load the XamlObject
        StringReader stringReader = new StringReader(savedObject);
        System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader);
        T target = (T)System.Windows.Markup.XamlReader.Load(xmlReader);

        return target;
    }

答案 1 :(得分:3)

如果您尝试克隆UIElements,请使用XamlWriter保存为字符串,但没有任何克隆方法是万无一失的。然后使用XamlReader加载副本。你仍然可能遇到问题。像处理程序没有被复制,x:名称被复制等等。但对于像Grid或Brush这样的简单元素,它的效果很好。

编辑1:但是,没有通用的方法可以克隆任何内容:

1)如果正确编写了克隆函数,它将为您调用基本克隆,并复制基类类。如果没有正确写入调用基础克隆将无济于事,尽管您可以调用私有方法this way

2)如果必须,你可以使用Reflection来复制几乎任何东西,甚至点击处理程序,从旧对象到新对象。

3)XamlWriter和XamlReader将复制和实例化对象的heirarchies,只是减去某些属性。

编辑2:这是我在类层次结构中使用的常见克隆设计模式。假设基类形状,派生类圈:

protected Circle(Circle t)
{
    CopyFrom(t);
}

public override object Clone()
{
    return new Circle(this);
}

protected void CopyFrom(Circle t)
{
    // Ensure we have something to copy which is also not a self-reference
    if (t == null || object.ReferenceEquals(t, this))
        return;

    // Base
    base.CopyFrom((Shape)t);

    // Derived
    Diameter = t.Diameter;
}

答案 2 :(得分:0)

我自己没有尝试过,但XamlWriter看起来很有希望。