views:

55

answers:

1

WHY! doesn't this dispose of all the objects on the flow panel!? the count shows 5 and there are 5 buttonsWithProperties on the form, no other objects are on the form.

foreach (ButtonWithProperties itemButton in flowLayoutPanel1.Controls)
        {
            itemButton.Dispose();
        }

It disposes 3 of the object but not the last 2...

+2  A: 

Indeed it's a bad practice to Dispose() an object to which there is a live reference (in your visual tree). If you want to remove the buttons, you perhaps have to remove them from Controls in an orderly way. See http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection.removeat.aspx.

Edit:
Please note that the button is an IDisposable, therefore the version with RemoveAt needs an explicit Dispose:

var controls = flowLayoutPanel1.Controls;
for (int i = controls.Count - 1; i >= 0; --i)
{
    var c = controls[i];
    if (c is ButtonWithProperties)
    {
        flowLayoutPanel1.Controls.RemoveAt(i);
        c.Dispose();
    }
}

Edit:
The documentation suggests that Dispose should be called even if one is using Clear. So if you don't need the buttons any more, you should Dispose() them.

Vlad
the remove option behaves the same way it leaves 2 or 3 bof the 5 buttons each time!
Adrian
I can't access the link for some reason guess MS are having problems too!
Adrian
@Adrian: Just look up "Control.ControlCollection.RemoveAt Method" at MSDN
Vlad
@Adrian: could you please post your code with RemoveAt which fails?
Vlad
I just tried flowLayoutPanel1.Controls.Clear(); which works fine!Thanks for your help.
Adrian
@Adrian: beware that `Clear()` will remove all the child controls, not only that of type `ButtonWithProperties`.
Vlad
thanks but that ok for me it only has that type on it...I found out why its not working i was looping forward for (int i = flowLayoutPanel1.Controls.Count; i > 0; i--) { flowLayoutPanel1.Controls.RemoveAt(i-1); }Works can you do a for each backwards!?
Adrian
@Adrian: for selective deletion you need something like `for (int i = flowLayoutPanel1.Controls.Count - 1; i >= 0; --i) if (flowLayoutPanel1.Controls[i] is ButtonWithProperties) flowLayoutPanel1.Controls.RemoveAt(i);` Note that you need to iterate from the back :-)
Vlad
@Adrian: It will work forward with the following code: `for (int i = 0; i < flowLayoutPanel1.Controls.Count; /* nothing */) if (flowLayoutPanel1.Controls[i] is ButtonWithProperties) flowLayoutPanel1.Controls.RemoveAt(i); else ++i;` Note that deletion shifts the indices :-)
Vlad
Vlad, thank you for your help.
Adrian
@Adrian - beware that calling RemoveAt() without calling Dispose() is a unpluggable leak.
Hans Passant
@Hans: Indeed, unlike WPF the WinForms button is IDisposable. I'll add this to the answer, thank you for the hint.
Vlad