Dot-Net

UserControl 句柄多久重新創建一次?

  • July 22, 2011

我在 msdn 上查找了 Winforms 的 UserControl.Load 事件(在此處找到),並看到了以下警告消息:

在創建 UserControl 的句柄時發生 Load 事件。在某些情況下,這可能會導致 Load 事件發生多次。例如,載入 UserControl 時會發生 Load 事件,如果重新創建句柄則再次發生。(重新創建句柄的一種方法是呼叫 RecreateHandle 方法。)要考慮多次發生的 Load 事件,您應該將任何一次初始化程式碼放在 UserControl 建構子中,而不是 Load 事件處理程序中。此外,您不應在 Load 事件處理程序中將數據綁定添加到 UserControl。

那麼我的問題是,除了顯式呼叫 RecreateHandle 之外,還有什麼會導致為 UserControl 重新創建句柄?在閱讀本文之前,我總是將任何應該只發生一次的事情放在 Load 事件中。另外(從最後一句話),添加數據綁定的最佳位置在哪裡?如果我不打算呼叫 RecreateHandle 真的很重要嗎?

是的,這是可能的。它是由本機 Windows CreateWindowEx() API 函式的問題引起的。該呼叫指定視窗的樣式位。這些相同的樣式位也作為控制項的屬性公開。問題是,更改該屬性需要再次呼叫 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");
   }
}

編譯並將控制項放到窗體上。添加一個按鈕:

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

並觀察每次點擊按鈕時輸出視窗都會顯示“onload”。

RightToLeft 屬性是我能想到的唯一一個用於執行此操作的 UserControl。表格還有很多。然而,該類有專門的程式碼來防止其 OnLoad 方法執行不止一次。不知道他們為什麼不為 UserControl 這樣做,可能是因為它非常罕見。隨意忽略它。除非您關心視窗大小,否則始終支持建構子而不是 Load 事件。

引用自:https://stackoverflow.com/questions/6796067