none
How to clone a WPF Object?

    Question

  • Hello All,

    I'm creating a user interface in my WPF application and I need to show more than one instance of a GeometryPath object. As you may know, if I try to specify more than on father to an elment, I get the following exception:

    System.InvalidOperationException: The specified element is already the logical child fo another element. Disconnect it first.

    So I need to clone this GeometryPath as many times I need.

    I tried to create a new GeometryPath instance and clone the data property using originalObject.Data.Close() method, but instead of the exception, I got nothing actually drawn in the object...

    Could you please give me a hand on this issue?

    For Example:

    System.Windows.Shapes.Path newPath = new System.Windows.Shapes.Path();
    newPath.Data = piece.PathGeometry.Data.Clone();
    
    What might be wrong?

    Thanks in Advance,

    Igor


    Project Manager at INOVATIVA Tecnologia www.inovativatec.com
    Friday, July 10, 2009 5:36 PM

Answers

  • Vineeth Paliath's code only works for Path scenario, and he uses XAML serialization/deserialization which is not performant enough (and even unworkable in some edge scenarios) in this case. Please use my code which works for general purpose 2D visual, aka it could visually copy any type of System.Windows.Media.Visual object.

    Hope this makes sense to you.
    Another Paradigm Shift! http://shevaspace.blogspot.com
    Monday, July 13, 2009 4:16 PM
  • Hi Igor,
    you an element can only have one Parent, otherwise visual tree will get confused. You probably got an error message, saying that you have to disconnect your path from its parent. There's a way to clone elements, here's the snippet:

    string xaml = XamlWriter.Save(newPath);

     if (xaml != null)
                         {

                             using (System.IO.MemoryStream stream = new System.IO.MemoryStream(xaml.Length))
                             {

                                 using (System.IO.StreamWriter sw = new System.IO.StreamWriter(stream))
                                 {

                                     sw.Write(xaml);

                                     sw.Flush();

                                     stream.Seek(0, System.IO.SeekOrigin.Begin);

                                     UiElement clonePath= XamlReader.Load(stream) as UiElement;
                                  }
                               }
                           }

    Vineeth
    Monday, July 13, 2009 4:30 AM

All replies

  • Hi Igor,
    you an element can only have one Parent, otherwise visual tree will get confused. You probably got an error message, saying that you have to disconnect your path from its parent. There's a way to clone elements, here's the snippet:

    string xaml = XamlWriter.Save(newPath);

     if (xaml != null)
                         {

                             using (System.IO.MemoryStream stream = new System.IO.MemoryStream(xaml.Length))
                             {

                                 using (System.IO.StreamWriter sw = new System.IO.StreamWriter(stream))
                                 {

                                     sw.Write(xaml);

                                     sw.Flush();

                                     stream.Seek(0, System.IO.SeekOrigin.Begin);

                                     UiElement clonePath= XamlReader.Load(stream) as UiElement;
                                  }
                               }
                           }

    Vineeth
    Monday, July 13, 2009 4:30 AM
  • I've written an example on how to visually clone a Visual and display it under the same visual tree without encountering visual re-parenting exception, you could refer to the code at the following link:

    http://cid-fd9a0f1f8dd06954.skydrive.live.com/self.aspx/Public/Code%20Samples/WPF/VisualCopyDemo.zip

    Note that this code doesn't consider Visual3D case.

    Hope this helps
    Another Paradigm Shift! http://shevaspace.blogspot.com
    Monday, July 13, 2009 4:31 AM
  • Vineeth Paliath's code only works for Path scenario, and he uses XAML serialization/deserialization which is not performant enough (and even unworkable in some edge scenarios) in this case. Please use my code which works for general purpose 2D visual, aka it could visually copy any type of System.Windows.Media.Visual object.

    Hope this makes sense to you.
    Another Paradigm Shift! http://shevaspace.blogspot.com
    Monday, July 13, 2009 4:16 PM
  • Hello Zhou,

    I tried Vineeth approach and it did work. But I believe Serialization might not fit all WPF classes and it doesn't looks like performant. But in my case peformance is not a concern for the size of my problem. However, I will look your solution and maybe adopt it in my project.

    Thank you guys very much for the support...

    Igor
    Project Manager at INOVATIVA Tecnologia www.inovativatec.com
    Monday, July 13, 2009 4:39 PM
  • Please use my code which works for general purpose 2D visual, aka it could visually copy any type of System.Windows.Media.Visual object.

    Where is your code?

    I'm trying to copy/clone element also at the moment.

    Monday, October 12, 2009 10:55 AM
  • Hello Ciantic,

    I think this is what are you looking for, right?

    http://cid-fd9a0f1f8dd06954.skydrive.live.com/self.aspx/Public/Code%20Samples/WPF/VisualCopyDemo.zip

    If not, please let me know.

    Igor.
    Project Manager at INOVATIVA Tecnologia www.inovativatec.com
    Tuesday, October 27, 2009 5:15 PM
  • Hi Zhou,

    I'm working on Printing FlowDocument in my wpf app, and i need a function to repeat a tableRow, marked to be the header of the considered Table.

    I've look around, and found solutions that retrieve the visual tablerow from its container, then put it on the next page on top of following tablerows, but actually, the header is retrieve because of visual re-parenting exception coming if we don't do it.

    So I found this post talking about your visual-cloning example. I Downloaded your example but can't understand how to use it to clone a TableRow as a visual object .

    Any idea to do it ?....

    It seems like nobody in the wpf world has this need to repet table headers when printing flowdocument ... Am i wrong hihihi

    Thanks in advance,

    Vincent
    Tuesday, February 16, 2010 9:57 AM