首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

ISupportInitialize 介面實戰:解決 WinForms 設計器屬性初始化順序問題

     編輯:關於.NET

問題場景

開發複雜 WinForms 控件(如 OpenGLControl)時,某些屬性(BitDepth、FrameRate、RenderContextType)必須在 Size 之前設定,否則底層資源建立失敗。但設計器產生的 InitializeComponent 代碼順序不可控:

this.openGLControl1.BitDepth = 32;
this.openGLControl1.DrawRenderTime = true;
this.openGLControl1.FrameRate = 29.41176F;
this.openGLControl1.Location = new Point(12, 12);
this.openGLControl1.Name = "openGLControl1";
this.openGLControl1.RenderContextType = RenderContextType.NativeWindow;
this.openGLControl1.Size = new Size(768, 379); // 最後才設定 Size
this.openGLControl1.TabIndex = 0;

解決方案:實作 ISupportInitialize

當控件實作 System.ComponentModel.ISupportInitialize,設計器會自動在 InitializeComponent 中包裹 BeginInit()/EndInit():

private void InitializeComponent() {
    // ...
    this.openGLControl1 = new SharpGL.OpenGLControl();
    ((ISupportInitialize)(this.openGLControl1)).BeginInit();
    this.SuspendLayout();
    // ... 所有屬性設定代碼 ...
    ((ISupportInitialize)(this.openGLControl1)).EndInit();
    this.ResumeLayout(false);
    this.PerformLayout();
}

實作範例

public class OpenGLControl : Control, ISupportInitialize {
    private bool _initializing = false;
    
    public int BitDepth { get; set; }
    public float FrameRate { get; set; }
    public RenderContextType RenderContextType { get; set; }
    // ... 其他相依屬性

    public void BeginInit() {
        _initializing = true;
    }

    public void EndInit() {
        _initializing = false;
        // 此處所有屬性已設定完成,安全建立底層資源
        RecreateRenderContext(); // 依賴 BitDepth、Size 等
    }

    protected override void OnSizeChanged(EventArgs e) {
        if (!_initializing) RecreateRenderContext();
        base.OnSizeChanged(e);
    }
}

核心機制

  • BeginInit:標記進入批次初始化階段,暫停副作用邏輯(如資源建立、事件觸發)。
  • EndInit:標記初始化結束,統一執行依賴多個屬性的初始化邏輯,這是最早可安全執行的時機。
  • 設計器自動識別:只要型別實作 ISupportInitialize,即自動生成包裹代碼,無需額外設定。

適用場景

  • 屬性間有嚴格初始化順序相依(如:必須先設定格式、再設定大小)。
  • 批次設定屬性時需避免重複昂貴運算(如:每次設定 DataSource 都觸發查詢)。
  • 元件需在設計時期與運行時期行為一致。

參考來源

原文:Dave Kerr - How ISupportInitialize Can Help

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved