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

C# 擴展方法進階實戰:WinForms 控制項選擇器

     編輯:關於C#

前言

WinForms 容器控制項 (Form、Panel、GroupBox) 形成控制項樹。本文實作 GetControls<T> 擴展,支援型別篩選、條件過濾、遞迴遍歷,讓批次操作控制項如同 LINQ 查詢般簡潔。

控制項繼承結構速覽

  • Control → ScrollableControl → ContainerControl → Form
  • Control → ButtonBase → Button, CheckBox, RadioButton
  • Control → TextBoxBase → TextBox, RichTextBox
  • Control → ListControl → ListBox, ComboBox

核心擴展實作

public static IEnumerable<T> GetControls<T>(
    this Control parent,
    Func<T, bool> predicate = null) where T : Control
{
    foreach (Control child in parent.Controls)
    {
        if (child is T typed)
        {
            if (predicate == null || predicate(typed))
                yield return typed;
            // 繼續遞迴搜尋子控制項 (容器控制項可能同時符合型別條件)
            foreach (var descendant in child.GetControls(predicate))
                yield return descendant;
        }
        else
        {
            // 非目標型別,仍需遞迴搜尋其子控制項
            foreach (var descendant in child.GetControls(predicate))
                yield return descendant;
        }
    }
}

// 輔助:ForEach 擴展
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach (var item in source) action(item);
}

實戰應用範例

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        
        // 1. 禁用所有按鈕
        this.GetControls<Button>().ForEach(b => b.Enabled = false);
        
        // 2. 反轉 GroupBox1 內所有 CheckBox 狀態
        this.GetControls<CheckBox>(c => c.Parent == groupBox1)
            .ForEach(c => c.Checked = !c.Checked);
        
        // 3. 設定特定 Label 顏色
        this.GetControls<Label>(l => l.Name == "label1")
            .FirstOrDefault()?.ForeColor = Color.Red;
        
        // 4. 取得所有 TextBox 並清空
        this.GetControls<TextBox>().ForEach(t => t.Clear());
        
        // 5. 複雜條件:啟用所有可見且可編輯的 TextBox
        this.GetControls<TextBox>(t => t.Visible && t.ReadOnly == false)
            .ForEach(t => t.BackColor = Color.White);
    }
}

進階變體:依容器類型篩選

// 僅搜尋 Panel 容器內的控制項
public static IEnumerable<T> GetControlsIn<T>(
    this Control parent,
    Func<T, bool> predicate = null) where T : Control
{
    foreach (Control child in parent.Controls)
    {
        if (child is Panel panel)
        {
            foreach (var ctrl in panel.GetControls(predicate))
                yield return ctrl;
        }
    }
}

注意事項

  1. 效能:大量控制項時遞迴遍歷有開銷,建議快取結果或僅在必要時呼叫。
  2. 動態控制項:運行時動態加入/移除的控制項會即時反映在遍歷結果中。
  3. 型別約束:where T : Control 確保型別安全,避免無效轉型。

結語

控制項選擇器將「尋找控制項」與「操作控制項」解耦,配合 Lambda 運算式實現聲明式 UI 操作,大幅減少巢狀迴圈與型別檢查代碼,是 WinForms 開發的必備工具方法。

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