如何克隆WPF对象?

38 c# wpf binding clone

任何人都有一个很好的例子如何深度克隆WPF对象,保留数据绑定?


明确的答案是第一部分.

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

Ala*_* Le 60

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

例:将对象写入xaml(假设该对象是一个Grid控件):

string gridXaml = XamlWriter.Save(myGrid);
Run Code Online (Sandbox Code Playgroud)

将其加载到一个新对象:

StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newGrid = (Grid)XamlReader.Load(xmlReader);
Run Code Online (Sandbox Code Playgroud)

  • 需要明确的是,这只是解决方案的一半(因为它在08年回顾).这将导致评估绑定并将结果序列化.如果你想保留绑定(如问题所示)你必须在运行时将ExpressionConverter添加到Binding类型(请参阅我的问题的第二部分以获取相关链接)或者在下面看看我自己的答案,了解如何在4.0中执行此操作. (7认同)

小智 34

在.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();
Run Code Online (Sandbox Code Playgroud)

  • @JP抱歉,这不是那么清楚....问题是如何克隆*同时保留绑定*.明确的答案是正确的一半; 事实上,如果你这样做,你会发现你的绑定将被评估,结果(而不是绑定本身)将被序列化.在我的问题中,我将后半部分添加到解决方案中,即添加ExpressionConverter并在运行时将其添加到Binding类型.它有点模糊.这个答案可以完成同样的事情 - 请参阅HERE BE MAGIC评论?这指示序列化程序**不能**在序列化时评估绑定.整齐. (5认同)

Joh*_*ski 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.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)