Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an easy/built-in way to get an exact copy (clone) of a XAML element?

Tags:

c#

clone

wpf

xaml

I need to make areas of XAML printable and so have make this button handler:

private void Button_Click_Print(object sender, RoutedEventArgs e)
{
    Customer.PrintReport(PrintableArea);
}

And in PrintReport I pack the frameworkelement into other elements in order to print it in a slightly different way than it is on the screen, like this:

public void PrintReport(FrameworkElement fwe)
{
    StackPanel sp = new StackPanel();
    sp.Children.Add(fwe);
    TextBlock tb = new TextBlock();
    tb.Text = "hello";
    sp.Children.Add(tb);

    PrintDialog dialog = new PrintDialog();
    if (dialog.ShowDialog() == true)
    { 
        dialog.PrintVisual(sp, "Print job"); 
    }
}

But the above gives me the following error:

Specified element is already the logical child of another element. Disconnect it first.

Is there an easy way to clone the FrameworkElement so that I can manipulate the copy, print it, and then forget about it, leaving the original element in the XAML being displayed on the screen intact?

Something like this I would imagine:

FrameworkElement fwe2 = FrameworkElement.Clone(fwe); //pseudo-code
like image 686
Edward Tanguay Avatar asked Dec 28 '09 09:12

Edward Tanguay


1 Answers

I had a similar problem in my current project and solved it with this code.

public static class ExtensionMethods
{
    public static T XamlClone<T>(this T original)
        where T : class
    {
        if (original == null)
            return null;

        object clone;
        using (var stream = new MemoryStream())
        {
            XamlWriter.Save(original, stream);
            stream.Seek(0, SeekOrigin.Begin);
            clone = XamlReader.Load(stream);
        }

        if (clone is T)
            return (T)clone;
        else
            return null;
    }
}

This way it simply appears as a method on all objects in your WPF project, you do not need to give any parameters to the method, and it returns an object of the same class as the original.

like image 135
reSPAWNed Avatar answered Sep 19 '22 14:09

reSPAWNed