0

The three ImageButtons below are added to a panel (pBreakfast) in a page's codebehind:

ImageButton ibSR = new ImageButton();
ibSR.ID = "ibStickyRoll";
ibSR.ImageUrl = "/images/Breakfast.gif";
ibSR.Click += new ImageClickEventHandler(ImageButton_Click);
pBreakfast.Controls.Add(ibSR);

ImageButton ibD = new ImageButton();
ibD.ID = "ibDoughnut";
ibD.ImageUrl = "/images/Breakfast.gif";
ibD.Click += new ImageClickEventHandler(ImageButton_Click);
pBreakfast.Controls.Add(ibD);
ibD.Dispose();

using(ImageButton ibC = new ImageButton()){
   ibC.ID = "ibCrepe";
   ibC.ImageUrl = "/images/Breakfast.gif";
   ibC.Click += new ImageClickEventHandler(ImageButton_Click);
   pBreakfast.Controls.Add(ibC);
}

I expected either all three would work, or perhaps the disposed ImageButtons would generate an error or simply not appear. But what's happening is all three appear and don't cause any errors, but the event handler never fires for the ImageButtons that are disposed.

Why does disposing cause only the eventhandler hookup to go away?

I am dynamically adding TableRow's and TableCell's to a table on this same page and placing ImageButtons in one cell of each row. I am using 'using' with the TableRow's and TableCell's without any problem. There doesn't seem to be an issue with the outer (TableRow & TableCell) objects getting disposed; as long as I don't ever dispose of the dynamic ImageButtons, the eventhandler gets fired OK on click.

Is it OK, in this instance, to not ever dispose of the ImageButtons? I have taken StackOverflow's advice to heart and try to use using() on all my disposable objects -- so this is really bugging me.

Thanks!

Michael Gorsich
  • 327
  • 1
  • 10

1 Answers1

1

Only Dispose an object after everything is completely done with it. Trying to do anything with the object after it is disposed will result in undefined behavior. Think of it as freeing the memory.

Fortunately, Windows forms disposes these objects for you when you close the form. The only case you would need to dispose them in your code is if you remove the objects from the form.

Take a look at the .Designer.cs file, and you will see the form's Dispose() method:

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
}

The components.Dispose() will recursively clean up all the components on the form, including those in the panel.

Moby Disk
  • 3,761
  • 1
  • 19
  • 38
  • Thanks for the reply, Moby. I can't help but think there is more to it than that, though. Is the dispose() happening immediately even though there's a ref to it in pBreakfast? I thought that the new ImageButton in the pBreakfast.controls now belonged to pBreakfast and the dispose wouldn't happen until pBreakfast was cleaned up. This is pretty confusing to me. Why is ImageButton disposable if I'm not supposed to dispose of it after the .Add()? Also, there isn't a designer.cs for this solution (at least I couldn't find one), I'm using compile on demand on the server. :^) – Michael Gorsich Jan 24 '14 at 11:44
  • The dispose is not happening immediately. It only happens when something calls Dispose() explicitly. You are correct when you say that the new ImageButton in pBreakfast.controls now belongs to pBreakfast and the dispose won't happen until pBreakfast is cleaned up. That is exactly what you want. After something calls Dispose() on the ImageButton, the ImageButton is useless. dead. kaput. You do not want to create an ImageButton, give it to pBreakfast, then destroy it! ImageButton is disposable so that it can be cleaned up after the form goes away entirely. – Moby Disk Jan 24 '14 at 14:45
  • Also, I am a doof and missed that this was ASP.NET not WinForms. Sorry about that. But it still stands: don't dispose of the object while someone else is using it. – Moby Disk Jan 24 '14 at 14:50
  • Just to close this up, would you say that the right way to dynamically add a table row is to not explicitly dispose of the TableRow, it's TableCells's, or any contents of the TableCells (e.g., ImageButtons) regardless of whether the page works with explicit disposals on some of the objects? Or if the page works with the disposals in place, leave them in? – Michael Gorsich Jan 24 '14 at 15:45
  • Aha! Check these out: http://stackoverflow.com/questions/3150735 http://stackoverflow.com/questions/1192554 – Moby Disk Jan 24 '14 at 15:59
  • Great links, Moby. That cleared it up for me. Now I have to wonder why my searches didn't come across those two. Have a great day! – Michael Gorsich Jan 24 '14 at 16:20