Instead of trying to add the same Template_canvas1.Children
to the root
canvas, first make a copy of those Children
and then add the copy to the root
canvas.
public static T CloneXaml<T>(T source)
{
string xaml = XamlWriter.Save(source);
StringReader sr = new StringReader(xaml);
XmlReader xr = XmlReader.Create(sr);
return (T)XamlReader.Load(xr);
}
Then change your loop to:
foreach (var c in childrenList)
{
var copy = CloneXaml(c);
root.Children.Add(copy);
}
I haven't tested this code, so you may have to modify it a bit, but it should put you in the right direction.
Alternatively, you can probably use the code below which is copied from Dr Herbie's answer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using System.Reflection;
using Windows.UI.Xaml.Controls;
namespace UIElementClone {
public static class UIElementExtensions {
public static T DeepClone<T>(this T source) where T : UIElement {
T result; // Get the type
Type type = source.GetType(); // Create an instance
result = Activator.CreateInstance(type) as T;
CopyProperties<T>(source, result, type);
DeepCopyChildren<T>(source, result);
return result;
}
private static void DeepCopyChildren<T>(T source, T result) where T : UIElement {
// Deep copy children.
Panel sourcePanel = source as Panel;
if (sourcePanel != null) {
Panel resultPanel = result as Panel;
if (resultPanel != null) {
foreach (UIElement child in sourcePanel.Children) {
// RECURSION!
UIElement childClone = DeepClone(child);
resultPanel.Children.Add(childClone);
}
}
}
}
private static void CopyProperties<T>(T source, T result, Type type) where T : UIElement {
// Copy all properties.
IEnumerable<PropertyInfo> properties = type.GetRuntimeProperties();
foreach (var property in properties) {
if (property.Name != "Name") { // do not copy names or we cannot add the clone to the same parent as the original.
if ((property.CanWrite) && (property.CanRead)) {
object sourceProperty = property.GetValue(source);
UIElement element = sourceProperty as UIElement;
if (element != null) {
UIElement propertyClone = element.DeepClone();
property.SetValue(result, propertyClone);
}
else {
try {
property.SetValue(result, sourceProperty);
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex);
}
}
}
}
}
}
}
}
If none of these worked for you, I'm afraid you'd have to implement your own serializer. It looks like David Poll implemented a decent serlizer, so have a look. Using his serlizer is as simple as using the XamlWriter
, then you can use the XamlReader
:
public static T CloneXaml<T>(T source)
{
UiXamlSerializer uxs = new UiXamlSerializer();
string xaml = uxs.Serialize(source);
StringReader sr = new StringReader(xaml);
XmlReader xr = XmlReader.Create(sr);
return (T)XamlReader.Load(xr);
}
To get this functionality, download his Slab library, go to the "Binaries" folder and copy all the dlls that start with "SLaB.Utilities.Xaml.Serializer" to your project. There might be some other dlls required as dependency. He has example solution in the library if you like to look at the code an learn.