¿Cómo se puede clonar un objeto WPF?

¿Alguien tiene un buen ejemplo de cómo clonar profundamente un objeto WPF, preservando las conexiones de datos?


La respuesta marcada es la primera parte.

La segunda parte es que debes crear un ExpressionConverter e insertarlo en el proceso de serialización. Los detalles para esto están aquí:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

La forma más sencilla en que lo hice es utilizar un XamlWriter para guardar el objeto WPF como una cadena. El método Save serializará el objeto y todos sus elementos secundarios en el árbol lógico. Ahora puede crear un nuevo objeto y cargarlo con un XamlReader.

ej .: Escribe el objeto en xaml (digamos que el objeto era un control de cuadrícula):

string gridXaml = XamlWriter.Save(myGrid); 

Cargarlo en un nuevo objeto:

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

En .NET 4.0, la nueva stack de serialización xaml hace MUCHO más fácil.

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

Aquí hay algunas buenas respuestas. Muy útil. Probé varios enfoques para copiar información vinculante, incluido el enfoque descrito en http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-progtwigtically/ pero ¡la información aquí es la mejor en Internet!

Creé un método de extensión reutilizable para tratar con InvalidOperationException “La vinculación no se puede cambiar después de que se haya utilizado.” En mi caso, mantuve algún código que alguien escribió, y después de una importante actualización del framework DevExpress DXGrid, ya no funcionaba. Lo siguiente resolvió mi problema perfectamente. La parte del código donde devuelvo el objeto podría ser más agradable, y lo volveré a factorizar más adelante.

 ///  /// Extension methods for the WPF Binding class. ///  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."); } } } 

Qué tal si:

  public static T DeepClone(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; } } 

Por supuesto, este fondo clona cualquier objeto, y puede que no sea la solución más rápida en la ciudad, pero tiene el menor mantenimiento … 🙂