如何克隆 WPF 对象?

问题描述 投票:0回答:5

有人有一个关于如何深度克隆 WPF 对象、保留数据绑定的好例子吗?


标记的答案是第一部分。

第二部分是您必须创建一个ExpressionConverter并将其注入到序列化过程中。 详细信息在这里:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

c# wpf binding clone
5个回答
65
投票

我完成此操作的最简单方法是使用 XamlWriter 将 WPF 对象保存为字符串。 Save 方法将序列化逻辑树中的对象及其所有子对象。现在您可以创建一个新对象并使用 XamlReader 加载它。

例如: 将对象写入 xaml(假设该对象是网格控件):

string gridXaml = XamlWriter.Save(myGrid);

将其加载到新对象中:

StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newGrid = (Grid)XamlReader.Load(xmlReader);

37
投票

在 .NET 4.0 中,新的 xaml 序列化堆栈使这变得更加容易。

var sb = new StringBuilder();
var writer = XmlWriter.Create(sb, new XmlWriterSettings
{
    Indent = true,
    ConformanceLevel = ConformanceLevel.Fragment,
    OmitXmlDeclaration = true,
    NamespaceHandling = NamespaceHandling.OmitDuplicates, 
});
var mgr = new XamlDesignerSerializationManager(writer);

// HERE BE MAGIC!!!
mgr.XamlWriterMode = XamlWriterMode.Expression;
// THERE WERE MAGIC!!!

System.Windows.Markup.XamlWriter.Save(this, mgr);
return sb.ToString();

5
投票

这里有一些很好的答案。 很有帮助。 我尝试了各种复制绑定信息的方法,包括http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/中概述的方法 但是这里的信息是网上最好的!

我创建了一个可重用的扩展方法来处理 InvalidOperationException“绑定在使用后无法更改”。 在我的场景中,我正在维护某人编写的一些代码,在主要的 DevExpress DXGrid 框架升级之后,它不再起作用。 以下完美解决了我的问题。 我返回对象的代码部分可能会更好,稍后我将重新考虑它。

/// <summary>
/// Extension methods for the WPF Binding class.
/// </summary>
public static class BindingExtensions
{
    public static BindingBase CloneViaXamlSerialization(this BindingBase binding)
    {
        var sb = new StringBuilder();
        var writer = XmlWriter.Create(sb, new XmlWriterSettings
        {
            Indent = true,
            ConformanceLevel = ConformanceLevel.Fragment,
            OmitXmlDeclaration = true,
            NamespaceHandling = NamespaceHandling.OmitDuplicates,
        });
        var mgr = new XamlDesignerSerializationManager(writer);

        // HERE BE MAGIC!!!
        mgr.XamlWriterMode = XamlWriterMode.Expression;
        // THERE WERE MAGIC!!!

        System.Windows.Markup.XamlWriter.Save(binding, mgr);
        StringReader stringReader = new StringReader(sb.ToString());
        XmlReader xmlReader = XmlReader.Create(stringReader);
        object newBinding = (object)XamlReader.Load(xmlReader);
        if (newBinding == null)
        {
            throw new ArgumentNullException("Binding could not be cloned via Xaml Serialization Stack.");
        }

        if (newBinding is Binding)
        {
            return (Binding)newBinding;
        }
        else if (newBinding is MultiBinding)
        {
            return (MultiBinding)newBinding;
        }
        else if (newBinding is PriorityBinding)
        {
            return (PriorityBinding)newBinding;
        }
        else
        {
            throw new InvalidOperationException("Binding could not be cast.");
        }
    }
}

0
投票

怎么样:

    public static T DeepClone<T>(T from)
    {
        using (MemoryStream s = new MemoryStream())
        {
            BinaryFormatter f = new BinaryFormatter();
            f.Serialize(s, from);
            s.Position = 0;
            object clone = f.Deserialize(s);

            return (T)clone;
        }
    }

当然,这个深度克隆任何对象,它可能不是城里最快的解决方案,但它的维护最少......:)


0
投票

就用这个:

string json = JsonConvert.SerializeObject(OldObj);
ObjectType NewOBJ = JsonConvert.DeserializeObject<ObjectType>(json);
© www.soinside.com 2019 - 2024. All rights reserved.