Frage

Hat jemand ein gutes Beispiel, wie man ein WPF-Objekt tief klont und dabei die Datenbindungen beibehält?


Die markierte Antwort ist der erste Teil.

Der zweite Teil besteht darin, dass Sie einen ExpressionConverter erstellen und ihn in den Serialisierungsprozess einbinden müssen.Details hierzu finden Sie hier:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

War es hilfreich?

Lösung

Der einfachste Weg, den ich gemacht habe, besteht darin, einen XamlWriter zu verwenden, um das WPF-Objekt als Zeichenfolge zu speichern.Die Save-Methode serialisiert das Objekt und alle seine untergeordneten Elemente in der logischen Baumstruktur.Jetzt können Sie ein neues Objekt erstellen und es mit einem XamlReader laden.

ex:Schreiben Sie das Objekt in xaml (sagen wir, das Objekt wäre ein Grid-Steuerelement):

string gridXaml = XamlWriter.Save(myGrid);

Laden Sie es in ein neues Objekt:

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

Andere Tipps

In .NET 4.0 macht der neue XAML-Serialisierungsstapel dies VIEL einfacher.

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();

Hier gibt es einige tolle Antworten.Sehr hilfreich.Ich habe verschiedene Ansätze zum Kopieren von Bindungsinformationen ausprobiert, einschließlich des in http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatical/ aber die Informationen hier sind die besten im Internet!

Ich habe eine wiederverwendbare Erweiterungsmethode für den Umgang mit InvalidOperationException erstellt. „Bindung kann nicht geändert werden, nachdem sie verwendet wurde.“ In meinem Szenario habe ich einen Code beibehalten, den jemand geschrieben hat, und nach einem großen Devexpress -DxGrid -Framework -Upgrade funktionierte es nicht mehr.Das Folgende hat mein Problem perfekt gelöst.Der Teil des Codes, in dem ich das Objekt zurückgebe, könnte schöner sein, und ich werde das später noch einmal umgestalten.

/// <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.");
        }
    }
}

Wie wäre es mit:

    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;
        }
    }

Natürlich klont diese Deep-Funktion jedes Objekt, und es ist vielleicht nicht die schnellste Lösung in der Stadt, aber sie erfordert den geringsten Wartungsaufwand ...:) :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top