auhmaan
auhmaan

Reputation: 726

Controls.Remove removing from controls but not from window

I'm trying to recreate a game in C# and I have a control that is composed with 3 objects:

The problem is, I have this code:

Orb[,] map = orbsAmmo;

for (Int32 x = 0; x < 2; x++)
    for (Int32 y = 0; y < 2; y++)
        orbsAmmo[x, y] = null;

for (Int32 index = this.Controls.Count - 1; index >= 0; index--)
    if (this.Controls[index] is Orb) {
        this.Controls[index].Parent = null;
        //this.Controls[index].Dispose();
        this.Controls.RemoveAt(index);
    }

//GC.Collect();

return map;

That works fine and removes the controls from the controls list, but the two Orbs that are supposed to be launched are still in the same location. If I try to see if the controls list still have the Orbs only appears the PictureBox of the Player.

I added the GC.Collect(); to collect the garbage, nothing happened.

It is something that I'm not seeing or missing?


SOLVED

Basically, the error occurs when I create the Orbs, I had Orb.parent = PictureBox to overlay correctly the images, because of the transparency, and doing that piece of code I had to remove the Orbs from the PictureBox and not from the main control, like I was trying to do.

Now it works fine and correctly.

Upvotes: 0

Views: 479

Answers (3)

Hans Passant
Hans Passant

Reputation: 941217

for (Int32 index = this.Controls.Count - 1; index >= 0; index--)
    if (this.Controls[index] is Orb) {
        this.Controls[index].Parent = null;
        //this.Controls[index].Dispose();
        this.Controls.RemoveAt(index);
    }

This code is buggy and will randomly remove controls. A control must have a Parent. If you set it to null then it will be removed from the parent's Control collection. You will now call RemoveAt() for another control. This may well be control that is not an Orb.

Calling the Dispose() method is not optional for controls. When you remove them from their Parent then they'll be re-hosted to the hidden parking window. Where they'll live, ready to moved to another parent. With high odds that this never happens, your program will leak controls. This cannot go endlessly, Windows refuses to allow you to create more windows after you've consumed 10,000 of them.

Not exactly a match with the complaint. Another thing that needs to happen for a control to visibly disappear is for the parent to repaint its background. Broken painting is common in gaming code.

Upvotes: 1

Nicolas Tyler
Nicolas Tyler

Reputation: 10552

You could try using a foreach and linq to dispose the orbs

IEnumerable<Control> c = GetAllOrbs(this);

foreach (Orb item in c.ToArray())
{
    item.Dispose();
    //or if you prefer just to remove them use this:
    //item.Parent.Controls.Remove(item);
}

.

public IEnumerable<Control> GetAllOrbs(Control control)
{
    var controls = control.Controls.Cast<Control>();

    return controls.SelectMany(ctrl => GetAllOrbs(ctrl, type)).Concat(controls).Where(c => c.GetType() == typeof(Orb));
}

You question is not clear, but from what i see in the code you want to remove the orbs.

Upvotes: 0

Sudhakar Tillapudi
Sudhakar Tillapudi

Reputation: 26199

if you are clearing/disposing Controls by index you will be definitely missing some of them because each time you clear/dispose a control their index will be changed.

Example : if you remove a Control at index0 -> control at index 1 becomes index 0, so next time when you try to remove control at index 1 you will skip to clear control at index 0

Try This:

this.Controls.Clear();

or

this.ControlPanel.Controls.Clear();

Upvotes: 0

Related Questions