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

C# Windows Forms 動態 ContextMenu 實作:多控制項共享單一選單

     編輯:關於C語言

前言

讓多個控制項共享單一 ContextMenu,並在 Popup 事件中動態調整選單項目,可減少元件數量、簡化維護。本文完整實作 CheckBox (三態) 與 RadioButton 共享選單的範例。

表單設計

  • checkBox1:ThreeState = true,ContextMenu = contextMenu1
  • radioButton1:ContextMenu = contextMenu1
  • contextMenu1:共享選單元件

核心邏輯:Popup 事件動態建構選單


private void contextMenu1_Popup(object sender, EventArgs e)
{
    // 1. 清除現有選單項
    contextMenu1.MenuItems.Clear();
    
    // 2. 基本項目:所有控制項通用
    contextMenu1.MenuItems.Add("選取 (&C)", new EventHandler(Checked_OnClick));
    contextMenu1.MenuItems.Add("取消選取 (&U)", new EventHandler(Unchecked_OnClick));
    
    // 3. 針對 CheckBox 動態加入「不確定」項目
    if (contextMenu1.SourceControl == checkBox1)
    {
        contextMenu1.MenuItems.Add("不確定 (&I)", new EventHandler(Indeterminate_OnClick));
    }
}

選單項目事件處理器

「選取」統一處理


private void Checked_OnClick(object sender, EventArgs e)
{
    // 根據來源控制項類型執行對應動作
    if (contextMenu1.SourceControl == radioButton1)
    {
        radioButton1.Checked = true;
    }
    else if (contextMenu1.SourceControl == checkBox1)
    {
        checkBox1.Checked = true;
    }
}

「取消選取」統一處理


private void Unchecked_OnClick(object sender, EventArgs e)
{
    if (contextMenu1.SourceControl == radioButton1)
    {
        radioButton1.Checked = false;
    }
    else if (contextMenu1.SourceControl == checkBox1)
    {
        checkBox1.Checked = false;
    }
}

「不確定」僅 CheckBox 適用


private void Indeterminate_OnClick(object sender, EventArgs e)
{
    if (contextMenu1.SourceControl == checkBox1)
    {
        checkBox1.CheckState = CheckState.Indeterminate;
    }
}

關鍵屬性:SourceControl

ContextMenu.SourceControl 回傳觸發選單的控制項參考,是動態選單的核心識別依據。

完整程式碼架構


public partial class DynamicContextMenuForm : Form
{
    public DynamicContextMenuForm()
    {
        InitializeComponent();
        
        // 設計器自動產生的關鍵設定:
        // checkBox1.ThreeState = true;
        // checkBox1.ContextMenu = contextMenu1;
        // radioButton1.ContextMenu = contextMenu1;
        // contextMenu1.Popup += contextMenu1_Popup;
    }
    
    private void contextMenu1_Popup(object sender, EventArgs e) { ... }
    private void Checked_OnClick(object sender, EventArgs e) { ... }
    private void Unchecked_OnClick(object sender, EventArgs e) { ... }
    private void Indeterminate_OnClick(object sender, EventArgs e) { ... }
}

擴充應用:多控制項類型共享選單


private void contextMenu1_Popup(object sender, EventArgs e)
{
    contextMenu1.MenuItems.Clear();
    
    Control source = contextMenu1.SourceControl;
    
    // 通用項目
    contextMenu1.MenuItems.Add("複製 (&C)", (s, e) => DoCopy(source));
    contextMenu1.MenuItems.Add("貼上 (&P)", (s, e) => DoPaste(source));
    contextMenu1.MenuItems.Add(new MenuItem("-")); // 分隔線
    
    // 型別專屬項目
    switch (source)
    {
        case TextBox txt:
            contextMenu1.MenuItems.Add("清空 (&L)", (s, e) => txt.Clear());
            contextMenu1.MenuItems.Add("全選 (&A)", (s, e) => txt.SelectAll());
            break;
        case ListBox lb:
            contextMenu1.MenuItems.Add("移除選取 (&R)", (s, e) => RemoveSelected(lb));
            contextMenu1.MenuItems.Add("排序 (&S)", (s, e) => lb.Sorted = !lb.Sorted);
            break;
        case DataGridView dgv:
            contextMenu1.MenuItems.Add("匯出 Excel (&E)", (s, e) => ExportToExcel(dgv));
            break;
    }
    
    contextMenu1.MenuItems.Add(new MenuItem("-"));
    contextMenu1.MenuItems.Add("屬性 (&R)", (s, e) => ShowProperties(source));
}

最佳實踐總結

原則說明
共享選單相似功能控制項共用一個 ContextMenu 元件
Popup 事件建構每次顯示前動態建構,確保狀態最新
SourceControl 識別以此屬性判斷來源控制項,執行對應邏輯
MenuItems.Clear()每次 Popup 開頭清除,避免項目重複累積
事件處理器複用通用動作 (複製/貼上) 共用處理器,型別專屬動作分開

注意事項

  • ContextMenu 為 .NET Framework 1.0 版本,新專案建議使用 ContextMenuStrip (功能更豐富、渲染更現代)
  • 動態建構選單有微小效能開銷,極高頻右鍵場景考慮快取
  • 巢狀選單需遞迴建構 MenuItem.MenuItems

總結

動態 ContextMenu 透過 Popup 事件 + SourceControl 識別 + MenuItems.Clear/Add 重建,實現多控制項共享單一選單元件且呈現差異化選項。此模式減少元件數量、集中邏輯、易於維護擴充。

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