Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How often is a UserControl handle recreated?

I looked up the UserControl.Load event for winforms (found here) on msdn and saw this caution message:

The Load event occurs when the handle for the UserControl is created. In some circumstances, this can cause the Load event to occur more than one time. For example, the Load event occurs when the UserControl is loaded, and again if the handle is recreated. (One way that a handle is recreated is by calling the RecreateHandle method.) To account for the Load event occurring more than one time, you should put any one time initialization code in the UserControl constructor instead of a Load event handler. In addition, you should not add data bindings to the UserControl in a Load event handler.

My question is then, what besides an explicit call to RecreateHandle will cause the handle to be recreated for a UserControl? Before reading this, I've always put anything that should only happen once in the Load event. Also (from the last sentence), where is the best place to add data bindings? Does it really matter if I'm not going to call RecreateHandle?

like image 594
TKTS Avatar asked Jul 22 '11 20:07

TKTS


1 Answers

Yes, this is possible. It is caused by a problem with the native Windows CreateWindowEx() API function. That call specifies style bits for the window. Those same style bits are also exposed as properties of the Control. Problem is, changing that property requires CreateWindowEx() to be called again. The native Windows window for the control is destroyed and recreated. That has side-effects, one of them is getting the Load event to run again.

Demonstrating it with a code sample:

public partial class UserControl1 : UserControl {
    public UserControl1() {
        InitializeComponent();
    }
    public void TriggerRecreate() {
        if (this.RightToLeft == System.Windows.Forms.RightToLeft.Yes)
             this.RightToLeft = System.Windows.Forms.RightToLeft.No;
        else this.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
    }
    protected override void OnLoad(EventArgs e) {
        base.OnLoad(e);
        Console.WriteLine("onload");
    }
}

Compile and drop the control on a form. Add a button:

    private void button1_Click(object sender, EventArgs e) {
        userControl11.TriggerRecreate();
    }

And observe that the Output window displays "onload" every time you click the button.

The RightToLeft property is the only one I can think of for a UserControl that will do this. There are many more for a Form. That class has however dedicated code to prevent its OnLoad method running more than once. Not sure why they didn't do this for UserControl, probably because it is so rare. Feel free to ignore it. And always favor the constructor over the Load event unless you care about the window size.

like image 164
Hans Passant Avatar answered Sep 17 '22 18:09

Hans Passant