Click here to Skip to main content
15,886,422 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I am attempting to clone a polygon exactly in order to display a zoomed in display of the polygon. I have a base class that when created creates a new polygon. I then have the draw method called that adds the polygon to a container that is passed to it.
VB
Public Sub Draw(ByRef container As System.Windows.Controls.Panel, ByVal table As ITable) Implements IMovableObject.Draw
    If Not container.Children.Contains(polygon) Then
        If container.GetType() Is GetType(Canvas) Then
            dYRatio = (container.ActualHeight / table.Height)
            dXRatio = (container.ActualWidth / table.Width)
            transforms.Children.OfType(Of ScaleTransform)()(0).ScaleY = -1 * dYRatio
            transforms.Children.OfType(Of ScaleTransform)()(0).ScaleX = dXRatio
            transforms.Children.OfType(Of TranslateTransform)()(0).Y = container.ActualHeight
            yInversionFactor = -1
            dContainerHeight = container.ActualHeight
        End If

        polygon.RenderTransform = transforms

        container.Children.Add(polygon)
    End If
End Sub


However when I attempt to add the cloned polygon to the container it gives me a "Specified element is already the logical child of another element. Disconnect it first." exception. The container the cloned polygon is being added to is an entirely different canvas then the original polygon. I've tried using Xaml.Save as well to clone the polygon and still receive the same results. Any help or ideas would be appreciated.



EDIT:
My clone method as requested.

VB
Public Overrides Function Clone() As Object
    Dim copy As New clsTrussSection(Me.Name)
    Dim ar As String = System.Windows.Markup.XamlWriter.Save(polygon)
    Dim poly As Polygon = System.Windows.Markup.XamlReader.Load(System.Xml.XmlReader.Create(New System.IO.StringReader(ar)))
    poly.Name = "Polygon" & Math.Floor((Rnd() * 10000)).ToString()

    For Each Point In MyBase.polygon.Points
        poly.Points.Add(New Point(Point.X, Point.Y))
    Next

    poly.RenderTransform = polygon.RenderTransform
    copy.polygon = poly
    Return copy
End Function
Posted
Updated 20-Mar-12 4:04am
v8

WPF is really nasty on reuse of visual elements. I would do a complete duplication of the element, and not depend on clone because clone usually is only a shallow copy. That means that the wpf will see the element in two places, and it does not like that. That is one of the reasons why Bill Wagner (Effective C#: 50 Specific Ways to Improve Your C#) does not consider Clone to be a good design pattern.

I have run into this problem at Microsoft, and we had a hell of a time with it.
 
Share this answer
 
All correct. The quick answer is: your check Contains is not correct (or not sufficient). You are checking that an element is not connected with some container as a child, but you are not checking if it is not connected with something else. Look at your own statement: "is being added to is an entirely different canvas". You need to know that it is not added to any other canvas or any other container as well.

If you need more detailed answer, you need to show more code: where the instance of the polygon is declared, created and cloned. Don't you think that asking a question about a problem in cloning and not showing your method called "Clone" (or something like that) is a bit strange? If you don't have such method, perhaps you should have it.

—SA
 
Share this answer
 
v3
Comments
Jake Gentry 20-Mar-12 9:49am    
I added my clone for your viewing enjoyment. I didn't want to make the question to beefy until I was sure I wasn't make some amateur mistake. This is the version using Xaml.save, I was previously just creating a new polygon object and transferring the points and the transforms.
Sergey Alexandrovich Kryukov 20-Mar-12 12:41pm    
Oh, I see... You are not cloning it, essentially. You are doing something which is not a deep clone (shallow clone at best), but doing... who knows what. A clone is a clone when you create everything from scratch. If you serialize and deserialize an instance (I would assume it would work), why would you add points to a new polygon? If you have deserialized clone already, why would you add the old points to a copy? Were they added already in deserealization? And, what could be the critical problem here, why do you copy RenderTransform? It's type Transform is a reference type. After your "clone" operation, you have two instances of the Polygon, both referencing the same instance of Transform, effectively shallowing the clone.

To start, try to get rid of this shared instance of Transform. Analyze all members of the instances of the Polygon: none of them should be common.

--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900