Question

Quelqu'un a un bon exemple de la façon de profondeur cloner un objet WPF, la préservation de databindings?


La forte réponse est la première partie.

La seconde partie est que vous devez créer un ExpressionConverter et à l'injecter dans le processus de sérialisation.Les détails de ce sont ici:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

Était-ce utile?

La solution

La façon la plus simple que j'ai fait c'est d'utiliser un XamlWriter pour enregistrer l'objet WPF comme une chaîne de caractères.La méthode Save va sérialiser l'objet et tous ses enfants dans l'arborescence logique.Maintenant, vous pouvez créer un nouvel objet et de le charger avec un XamlReader.

ex:Écrire l'objet de xaml (disons que l'objet était un contrôle de la Grille):

string gridXaml = XamlWriter.Save(myGrid);

De le charger dans un nouvel objet:

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

Autres conseils

Dans .NET 4.0, la nouvelle xaml sérialisation pile cela rend BEAUCOUP plus facile.

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

Il y a quelques grandes réponses ici.Très utile.J'avais essayé différentes approches pour la copie des informations de Liaison, y compris l'approche décrite dans http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/ mais l'information ici est le meilleur sur Internet!

J'ai créé un ré-utilisable de la méthode d'extension pour traiter InvalidOperationException “Liaison ne peut pas être changé après qu'il a été utilisé.” Dans mon scénario, j'ai été le maintien du code quelqu'un a écrit, et après une importante DevExpress DXGrid cadre de la mise à niveau, il ne travaillait plus.Le suivant a résolu mon problème à la perfection.La partie du code où je retourne l'objet pourrait être plus agréable, et je vais re-facteur que plus tard.

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

Comment à ce sujet:

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

Bien sûr, cette profonde clones n'importe quel objet, et il ne pourrait pas être la solution la plus rapide en ville, mais il a le moins d'entretien...:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top