Come si può clonare un oggetto WPF?
Domanda
Qualcuno ha un buon esempio di come profondo clonare un oggetto WPF, conservando databindings?
La marcata risposta è la prima parte.
La seconda parte è che è necessario creare un ExpressionConverter e inietta il processo di serializzazione.Dettagli per questo sono qui:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571
Soluzione
Il modo più semplice che ho fatto è quello di utilizzare un XamlWriter per salvare l'oggetto WPF come una stringa.Il metodo di Salvataggio sarà serializzare l'oggetto e tutti i suoi figli nell'albero logico.Ora è possibile creare un nuovo oggetto e lo carico con un XamlReader.
ex:Scrivere l'oggetto xaml (diciamo che l'oggetto era una Griglia di controllo):
string gridXaml = XamlWriter.Save(myGrid);
Caricare in un nuovo oggetto:
StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newGrid = (Grid)XamlReader.Load(xmlReader);
Altri suggerimenti
In .NET 4.0, il nuovo xaml serializzazione stack questo rende MOLTO più 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();
Ci sono alcuni grandi risposte qui.Molto utile.Ho provato vari approcci per la copia di informazioni di Associazione, compreso l'approccio descritto in http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/ ma le informazioni qui è il migliore su Internet!
Ho creato un riutilizzabili estensione del metodo per affrontare InvalidOperationException “Associazione non può essere modificato dopo che è stato usato.” Nel mio scenario, ero il mantenimento di un po ' di codice che qualcuno ha scritto, e dopo un grande DevExpress DXGrid framework di aggiornamento, non ha più lavorato.I seguenti risolto il mio problema perfettamente.La parte di codice dove ho restituire l'oggetto potrebbe essere più bello, e io ti ri-fattore che più tardi.
/// <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.");
}
}
}
Come circa:
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;
}
}
Naturalmente questo profondo cloni di qualsiasi oggetto, e potrebbe non essere la soluzione più veloce in città, ma è quello che ha meno manutenzione...:)