Tuesday, March 4, 2008

[Silverlight] Cloning an XAML element

BLAH!!! As of the time of writing this post, there is no way to 'Clone' a XAML element in Silverlight... at least none that I can find with my poor google skills.

MY APPROACH

Ideally what I'd like to do is be able to take an element and iterate through all of it's properties and make an exact copy of each property - thus creating an exact clone [except for the name, which I'd have to change].

I currently have a recursive function that will check what type of element the object is and the redirect to the corresponding 'clone' function, which makes exact copies of specific properties for that object. This is done recursively on all of the children of that element [if children exist].

public UIElement CloneUIElement(UIElement copyMe, string instance, Canvas parent)
{
return RecurseCloneUIElement(copyMe, instance, parent);
}

public UIElement RecurseCloneUIElement(UIElement copyMe, string instance, Canvas parent)
{
UIElement temp = copyMe as UIElement;
switch (copyMe.ToString())
{
case "System.Windows.Controls.Canvas":
temp = CloneCanvas((Canvas)copyMe, instance, parent);
break;
case "System.Windows.Shapes.Rectangle":
temp = CloneRectangle((Rectangle)copyMe, instance, parent);
break;
... [All I have is canvas and rect]
}
return temp;
}

public Canvas CloneCanvas(Canvas copyMe, string instance, Canvas parent)
{
Canvas clonedCanvas = new Canvas();
clonedCanvas.SetValue(Canvas.NameProperty, copyMe.GetValue(Canvas.NameProperty) + "_" + instance);
clonedCanvas.SetValue(Canvas.LeftProperty, (double)copyMe.GetValue(Canvas.LeftProperty));
clonedCanvas.SetValue(Canvas.TopProperty, (double)copyMe.GetValue(Canvas.TopProperty));
clonedCanvas.SetValue(Canvas.WidthProperty, (double)copyMe.GetValue(Canvas.WidthProperty));
clonedCanvas.SetValue(Canvas.HeightProperty, (double)copyMe.GetValue(Canvas.HeightProperty));

// ONLY CLONING SOLID BRUSHES AT THE MOMENT.
SolidColorBrush cloneColor = copyMe.GetValue(Canvas.BackgroundProperty) as SolidColorBrush;
if (cloneColor != null) { clonedCanvas.SetValue(Canvas.BackgroundProperty, cloneColor.Color.ToString()); }

foreach (Visual child in copyMe.Children)
{
clonedCanvas.Children.Add(RecurseCloneUIElement((UIElement)child, instance, clonedCanvas));
}
return clonedCanvas;
}

FREEZABLE OBJECTS

It appears that in the 3.0 framework there are 'freezable' objects, which include brushes. Apparently there is a clone functionality with those objects, however I'm guessing it's not included in the silverlight framework since I cannot access the functionality they are talking about.


Reference Links:
How to copy Shape object through C#?
Freezable .Clone Method