40

データバインディングを維持しながらWPFオブジェクトをディープクローンする方法の良い例はありますか?


マークされた答えは最初の部分です。

2 番目の部分は、ExpressionConverter を作成し、シリアル化プロセスに挿入する必要があることです。詳細はこちら:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

4

4 に答える 4

64

私が行った最も簡単な方法は、XamlWriter を使用して WPF オブジェクトを文字列として保存することです。Save メソッドは、論理ツリー内のオブジェクトとそのすべての子をシリアル化します。これで、新しいオブジェクトを作成し、XamlReader で読み込むことができます。

例: オブジェクトを xaml に書き込みます (オブジェクトが Grid コントロールであるとしましょう):

string gridXaml = XamlWriter.Save(myGrid);

それを新しいオブジェクトにロードします。

StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newGrid = (Grid)XamlReader.Load(xmlReader);
于 2008-08-28T18:38:06.887 に答える
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();
于 2011-02-11T19:52:37.190 に答える
5

ここにはいくつかの素晴らしい答えがあります。非常に役立ちます。http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/で概説されているアプローチを含む、バインディング情報をコピーするためのさまざまなアプローチを試しましたが、ここの情報はインターネット上で最高です!

InvalidOperationException「Binding cannot be changed after it has been used.」に対処するための再利用可能な拡張メソッドを作成しました。私のシナリオでは、誰かが書いたコードを保守していましたが、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.");
        }
    }
}
于 2013-02-06T22:54:28.953 に答える
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;
        }
    }

もちろん、これはあらゆるオブジェクトのディープ クローンを作成します。最速のソリューションではないかもしれませんが、メンテナンスは最小限で済みます... :)

于 2008-08-28T15:24:45.900 に答える