重新创建UserControl句柄的频率是多少?

TKT*_*KTS 8 .net events user-controls winforms

我在msdn上查找了winforms(在这里找到)的UserControl.Load事件并看到了这条警告消息:

创建UserControl的句柄时发生Load事件.在某些情况下,这可能导致Load事件多次发生.例如,加载UserControl时会发生Load事件,如果重新创建句柄,则会再次发生.(重新创建句柄的一种方法是调用RecreateHandle方法.)为了解决多次出现的Load事件,您应该在UserControl构造函数中放置任何一次初始化代码而不是Load事件处理程序.此外,您不应在Load事件处理程序中向UserControl添加数据绑定.

那么我的问题是,除了对RecreateHandle的显式调用之外,还会导致为UserControl重新创建句柄吗?在阅读本文之前,我总是把任何只应该在Load事件中发生过一次的事情.另外(从最后一句),添加数据绑定的最佳位置在哪里?如果我不打电话给RecreateHandle,这真的很重要吗?

Han*_*ant 7

是的,这是可能的.它是由本机Windows CreateWindowEx()API函数的问题引起的.该调用指定窗口的样式位.这些相同的样式位也作为Control的属性公开.问题是,更改该属性需要再次调用CreateWindowEx().控件的本机Windows窗口将被销毁并重新创建.这有副作用,其中一个是让Load事件再次运行.

使用代码示例演示它:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

在窗体上编译并删除控件.添加一个按钮:

    private void button1_Click(object sender, EventArgs e) {
        userControl11.TriggerRecreate();
    }
Run Code Online (Sandbox Code Playgroud)

并观察每次单击按钮时输出窗口显示"onload".

对于将执行此操作的UserControl,RightToLeft属性是我能想到的唯一属性.表格还有很多.但是,该类具有专用代码来防止其OnLoad方法多次运行.不知道为什么他们没有为UserControl做这个,可能是因为它是如此罕见.随意忽略它.并且总是喜欢构造函数而不是Load事件,除非您关心窗口大小.