3

I have a Winform with a panel that loads different user controls depending on user inputs.

// to load a user control
pnlContent.Controls.Add(uc1);

// to change to different user control
pnlContent.Controls.Clear();
pnlContent.Controls.Add(uc2);

What I notice is that when I clear pnlContent and re-add uc1, the uc1's Load event doesn't get triggered, i.e. uc1's Load event only gets triggered in the very first time uc1 gets added to the pnlContent.

Is there a way to have the Load event always triggered every time the user control gets added to the panel? If not, what are my options?

Please advise.

Eddie
  • 197
  • 1
  • 2
  • 11
  • Do this in the page init – Chamika Sandamal Jun 26 '13 at 15:25
  • uc1 is just being removed from the control collection. You could say uc1 = new YourUserControlType before you re add it and dispose of it when its removed, but it depends on your setup. All you're doing is readding the uc1 to the collection, not reloading it. – KreepN Jun 26 '13 at 15:26
  • unfortunately, i can't re-"new" uc1, gotta keep it around or user needs to re-enter inputs to uc1, otherwise. – Eddie Jun 26 '13 at 15:28
  • Page init event? I can't find it in the list of events of uc1. – Eddie Jun 26 '13 at 15:29
  • 1
    @Eddie if you want to perform some action on a Load event of your UserControl, you should move the code in the Load Event handler to a public method and call it everytime you want. – King King Jun 26 '13 at 15:30
  • @ChamikaSandamal the OP is asking for the existence of `Page init` event :))) I think he thought you asked an ASP.NET question :)) – King King Jun 26 '13 at 15:31
  • @KingKing:opps.. sorry my bad – Chamika Sandamal Jun 26 '13 at 15:38
  • @KingKing - that's an option. This way the parent form should call this public method. I'd prefer to have the logic stay in the user control itself - parent form just loads/unloads user controls. – Eddie Jun 26 '13 at 15:38

3 Answers3

6
  pnlContent.Controls.Clear();

You have to be very careful with this method, it doesn't do what you think it does. It does not dispose the controls on the panel, it merely removes them. The controls go to live on, their windows are hosted to the hidden "parking window". Ready to be moved back to another parent.

In many cases that does not happen and the control will leak forever. In your specific case it isn't quite that bad yet, you still have a reference to the control. Your uc1 variable stores it. The consequence however is that its Load event doesn't fire again, that only happens once.

So if you really need that Load event to fire then you should do this the proper way, actually dispose the controls on the panel:

 while (pnlContent.Controls.Count > 0) pnlContents.Controls[0].Dispose();

And then you have to create a new instance of whatever usercontrol type uc1 references. You'll then get the Load event to fire when you add it to the panel.

Another strong hidden message in this answer is that it is very likely that you shouldn't be using the Load event at all. In the vast majority of cases, code in the Load event handler belongs in the constructor. You only need Load if you need to know the Handle property or need to be sure that layout was calculated so that the final size of the control is known. That's rare.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Great explanation on Controls.Clear()! Yes, I do not want to dispose uc1; that's why I call Clear(). If I disposed uc1 and re-"new" it, the user will have to re-enter all the inputs on uc1. I'm moving away from Load event and extracting the logic to a public method and have the parent/main form calls it after adding uc1 to the pnlContent. – Eddie Jun 26 '13 at 15:59
  • @Eddie I don't understand why you have some code in your Load event but you still want to re-execute it when your UserControl is already loaded? That's not logical at all. – King King Jun 26 '13 at 16:03
  • KingKing & Hans Passant are correct. I shouldn't use Load event to execute/re-execute my code. I have extracted the code to a public method and have the parent/main form calls it after pnlContent.Controls.Add(uc1); – Eddie Jun 26 '13 at 18:35
  • That last paragraph solved my problem! I instantiated a Control twice and added each to a different parent control the Load method was only called once. Moving that code to the constructor fixed my issue. Not sure why the previous developer decided to use Load. – styfle Oct 31 '13 at 20:56
1

I have a control that acts like a toolbox, which is added and removed from another parent control as the user push a toggle button.

Instead of using the Load event (that triggers only the first time the control is added to its parent controls collection), I use the ParentChanged event.

Then I check the Parent property: if it is null, that means the control has been removed from its parent collection. If it is not, the control has just been added.

private void MyUserControl_ParentChanged(object sender, EventArgs e)
{
    try
    {
        if (this.Parent != null) 
        {
            // Perform initializations
        }
    }
    catch (Exception ex)
    {
        // Do my normal exception handling
    }
}
Larry
  • 17,605
  • 9
  • 77
  • 106
0

I think you can do:

uc1.load(this, null);

Because you only remove it, and add it again. You dont reinitialize it.

DatRid
  • 1,169
  • 2
  • 21
  • 46
  • What is the kind of `load`? – King King Jun 26 '13 at 15:28
  • Actually, if he says "the uc1's Load event doesn't get triggered" so I think he has a load event or sth like this ? I know its a WinFormApp, and i come from asp.net programming and there is allways a onInit etc Event. I think this is also available in Winforms and he does some code in there. – DatRid Jun 26 '13 at 15:32
  • Can't do as Load is an event handler not a method – Eddie Jun 26 '13 at 15:32
  • "doesn't get triggered" -> 2nd, 3rd, 4th, etc. time. It gets triggered 1st time "pnlContent.Control.Add(uc1)" – Eddie Jun 26 '13 at 15:33
  • Yep, okay. Well sorry, then my answer is useless i think. Just wanted to help ;) – DatRid Jun 26 '13 at 15:35
  • you can trigger that way in the class in which `Load` event is defined, even UserControl is not the class in which `Load` is defined, instead use `OnLoad` raising method, however the OP has to handle with instances of UserControl, unless he wants to create his own UserControl and add some public method to raise `Load` event. – King King Jun 26 '13 at 15:35
  • Well, and if you write a methode which you call from your Loadevent and also if you add your control again ? – DatRid Jun 26 '13 at 15:37