Click here to Skip to main content
15,908,906 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
Okay this may seem like an easy question but I can't seem to actually get it to work, and wonder if anybody can help me, or point me in the right direction as I have searched for an answer already but have drawn up blanks.

What I have is a flow layout panel, as the main panel on my Form. The reason for a flow layout panel is so I can easily add other panels to it without specifying location points (actually putting my Java layout manager knowledge to good use).

These other panels that are added to the flow layout panel are added dynamically by the actual user with a button marked "Add Panel". The button name is called btnAddPanel. When these panels are added, a button is also included in this panel (btndeleteButton) which when the user clicks is suppose to delete the panel which the button resides on (the parent panel of the button).

The problem is I can't seem to get the delete button to work. I sometimes can get the last panel that has been added to be removed, but even this is sometimes hit and miss.

When the user clicks the delete button on one of the panels, the parent panel needs to be removed.

This is the code I have already and the commented out parts are some left over pieces of code I have tried but failed to work. I have tried a lot more times to get it to work, but every attempt I have failed.

Any suggestions? Thanks :)

Public Class Form1

    Dim btndeleteButton As Button
    Dim dynamicPanel As Panel

    Private Sub btnAddPanel_Click(sender As System.Object, e As System.EventArgs) Handles btnAddPanel.Click

        dynamicPanel = New Panel
        dynamicPanel.Size = New System.Drawing.Size(357, 100)
        dynamicPanel.BackColor = Color.LightBlue

        btndeleteButton = New Button
        btndeleteButton.Width = 100
        btndeleteButton.Text = "Delete"
        AddHandler btndeleteButton.Click, AddressOf btndeleteButton_Click


        dynamicPanel.Controls.Add(btndeleteButton)

        FlowLayoutPanel1.Controls.Add(dynamicPanel)

    End Sub

    Private Sub btndeleteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

        'FlowLayoutPanel1().Controls.Remove(dynamicPanel)
        'btndeleteButton.Parent.Dispose()

    End Sub

  
End Class
Posted
Comments
[no name] 30-Nov-12 23:45pm    
Whats happening over here ? I mean is it giving you an error or what ??
Sergey Alexandrovich Kryukov 1-Dec-12 0:12am    
That's not exactly an exception; OP actually explained it, albeit not so accurately.
I explained how to resolve the problem -- please see my solution.
--SA

1 solution

The code is just dirty, due to sharing of the instance field Form1.dynamicPanel. Very dirty. Just look carefully.

When the panel and deleting button is just one, everything is good, but if you try adding and removing panels in butterfly manner, the effect of sharing this variable comes into play. You think that you delete the panel having the button you are clicking on, but in fact the other instance of a panel is used, the one which was last added in this line:
VB
FlowLayoutPanel1.Controls.Add(dynamicPanel) ' bad!


Can you see the problem now?

So, to resolve the problem, you should avoid passing reference to the shared field; remove the field Form1.dynamicPanel at all. You need to pass data used by an event handle through the arguments of the event handler. Do something like this:

Add a back reference to a panel to the instance of deleting button, using its Tag property:
VB
' Dim btndeleteButton As Button ' remove form class fields
' Dim dynamicPanel As Panel ' remove form class fields

Private Sub btnAddPanel_Click(sender As System.Object, e As System.EventArgs) Handles btnAddPanel.Click

    Dim btndeleteButton As Button ' make former field a stack variable
    Dim dynamicPanel As Panel ' this one, too

    dynamicPanel = New Panel
    dynamicPanel.Size = New System.Drawing.Size(357, 100)
    dynamicPanel.BackColor = Color.LightBlue

    btndeleteButton = New Button

    btndeleteButton.Tag = dynamicPanel ' button will remember
                                       ' the panel to delete

    ' ... the rest of your code
    ' ...

End Sub


In the handler code, type-cast sender to Button. It will also be the instance of the button clicked; now, extract an instance of the Panel from the button: takes Button.Tag and type-cast it to Panel. Remove this instance of a panel.

Problem solved.

Another solution is this: do it all in the code of the handler; extract an instance of Button by type-casting sender. Take Button.Parent and type-cast this Control to Panel: you can be sure that before deleting, this Control is certainly the required Panel. Remove it.

It will work, too.

[EDIT]

One more note: never ever use names like btnAddPanel_Click, Form1 and other auto-generated names. Give everything some semantic names. This is why you are given the Visual Studio refactorization engine. No underscores or numerics ("Label1", "Label2" and the like). In addition to the problems of maintenance and readability, you are violating (good) Microsoft naming conventions. Yes, Microsoft auto-generated code violates them, too, so what? These names are not designed to be kept; you are supposed to rename them all, to make them semantically sensible.

—SA
 
Share this answer
 
v4

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