Xác định điều khiển mà ContextMenuStrip được sử dụng


84

Tôi có một ContextMenuStripcái được gán cho một số hộp danh sách khác nhau. Tôi đang cố gắng tìm ra khi ContextMenuStripđược nhấp vào, ListBoxnó được sử dụng để làm gì. Tôi đã thử mã dưới đây để bắt đầu nhưng nó không hoạt động. Có sendergiá trị chính xác, nhưng khi tôi cố gắng gán nó cho menuSubmittednó thì nó là null.

private void MenuViewDetails_Click(object sender, EventArgs e)
{
    ContextMenu menuSubmitted = sender as ContextMenu;
    if (menuSubmitted != null)
    {
        Control sourceControl = menuSubmitted.SourceControl;
    }
}

Bất kỳ sự trợ giúp nào đều sẽ là tuyệt vời. Cảm ơn.

Sử dụng sự hỗ trợ bên dưới, tôi đã tìm ra:

private void MenuViewDetails_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
            if (menuItem != null)
            {
                ContextMenuStrip calendarMenu = menuItem.Owner as ContextMenuStrip;

                if (calendarMenu != null)
                {
                    Control controlSelected = calendarMenu.SourceControl;
                }
            }
        }

cảm ơn vì giải pháp tôi đang tìm kiếm. Tôi đã từng gặp vấn đề tương tự. nhưng tôi khuyên bạn không nên lồng tất cả các ifcâu lệnh đó và sử dụng if (menuItem == null) return;nếu bạn giống tôi và không muốn mã của bạn xử lý nó được lồng thêm 2 cấp không cần thiết.
Shawn Kovac

Câu trả lời:


123

Đối với một ContextMenu:

Vấn đề là sendertham số trỏ đến mục trên menu ngữ cảnh đã được nhấp vào, không phải chính menu ngữ cảnh.

Tuy nhiên, đó là một bản sửa lỗi đơn giản vì mỗi phương thứcMenuItem hiển thị một GetContextMenuphương pháp sẽ cho bạn biết phương thức nào ContextMenuchứa mục menu đó.

Thay đổi mã của bạn thành như sau:

private void MenuViewDetails_Click(object sender, EventArgs e)
{
    // Try to cast the sender to a MenuItem
    MenuItem menuItem = sender as MenuItem;
    if (menuItem != null)
    {
        // Retrieve the ContextMenu that contains this MenuItem
        ContextMenu menu = menuItem.GetContextMenu();

        // Get the control that is displaying this context menu
        Control sourceControl = menu.SourceControl;
    }
}

Đối với một ContextMenuStrip:

Nó sẽ thay đổi một chút nếu bạn sử dụng a ContextMenuStripthay vì a ContextMenu. Hai điều khiển không liên quan đến nhau và một thể hiện của cái này không thể được chuyển sang một thể hiện của cái kia.

Như trước đây, mục được nhấp vẫn được trả về trong sendertham số, vì vậy bạn sẽ phải xác định mục ContextMenuStripsở hữu mục menu riêng lẻ này. Bạn làm điều đó với Ownertài sản . Cuối cùng, bạn sẽ sử dụng thuộc SourceControltính để xác định điều khiển nào đang hiển thị menu ngữ cảnh.

Sửa đổi mã của bạn như vậy:

private void MenuViewDetails_Click(object sender, EventArgs e)
{
     // Try to cast the sender to a ToolStripItem
     ToolStripItem menuItem = sender as ToolStripItem;
     if (menuItem != null)
     {
        // Retrieve the ContextMenuStrip that owns this ToolStripItem
        ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;
        if (owner != null)
        {
           // Get the control that is displaying this context menu
           Control sourceControl = owner.SourceControl;
        }
     }
 }

@bluefeet: Sau đó, bạn có một cái gì đó sai khác. Tôi vừa thử nghiệm mã này với ba hộp danh sách khác nhau và mọi thứ đều hoạt động như mong đợi. Đăng thêm một số mã repro.
Cody Grey

2
@bluefeet: Tôi đã cập nhật mã trong câu trả lời của mình. Có một sự khác biệt lớn giữa ContextMenuContextMenuStrip. (À, và tôi thấy bạn đã tìm ra nó. Chà, tốt hơn hết là bạn nên tự học mọi thứ!)
Cody Grey

1
Tôi đã sử dụng sự kiện Opening để ghi lại SourceControl đã mở menu thành một biến cục bộ, sau đó tham chiếu đến biến đó khi xử lý các lần nhấp vào mục.
QuickDanger

1
@QuickDanger Vâng, SourceControlthật đáng buồn là tại thời điểm này, một Clicksự kiện của một mục ToolStripItemphụ của ContextMenuStripđã bị kích hoạt. Dường như ContextMenuStrip's Closedcháy sự kiện trước đó Clicksự kiện, mà có lẽ là nguyên nhân gây ra các vấn đề; Tôi giả sử thuộc tính bị xóa sau khi menu 'đóng'.
Nyerguds

1
@CodyGray Trên thực tế, nếu cây sâu hơn, bạn phải lặp lại chuỗi OwnerItemthuộc tính cho đến khi bạn tìm thấy một cây ToolStripItemContextMenuStripthuộc tính của nó Owner. Nhưng như tôi vừa nhận xét, nó không hoạt động; các SourceControltrên menu ngữ cảnh sẽ được null. Bạn đã nói rằng bạn không thể tái tạo nó mặc dù ... có thể vấn đề chỉ xảy ra với các menu sâu hơn một cấp? Của tôi sâu hai cấp độ phụ.
Nyerguds

3

Bài đăng cũ hơn, nhưng trong trường hợp ai đó như tôi bắt gặp nó:

Đối với ContextMenuStrip, những điều trên không phù hợp với tôi, nhưng nó dẫn đến việc tìm ra những gì đã làm.

void DeleteMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
    ContextMenuStrip menu = sender as ContextMenuStrip;
    Control sourceControl = menu.SourceControl;
    MessageBox.Show(sourceControl.Name);
}

Điều này đã cho tôi tên của điều khiển mong đợi. Bạn có thể đưa vào xác nhận, v.v. với câu lệnh if, tôi chỉ đăng để đi vào vấn đề.


Điều này chỉ hoạt động với các mục trực tiếp trong a ContextMenu. Vấn đề là ItemClickednó không kích hoạt khi nhấp vào các mục menu phụ ; họ cần Clicksự kiện của riêng họ sẽ có mục chính là người gửi, không phải menu.
Nyerguds

3

Tôi đã gặp rất nhiều khó khăn để làm cho bất kỳ mã nào trong số này hoạt động. Đây là giải pháp đơn giản nhất mà tôi có thể tìm thấy:

Đối với ContextMenuStrip:

    Control _sourceControl = null;
    private void contextMenuStrip_Opened(object sender, EventArgs e)
    {
        _sourceControl = contextMenuStrip.SourceControl;
    }

    private void contextMenuItem_Click(object sender, EventArgs e)
    {
        var menuItem = (ToolStripMenuItem)sender;

        _sourceControl.Text = menuItem.Text;
        MessageBox.Show(menuItem.Name);
        MessageBox.Show(sourceControl.Name);
    }

0

Giải pháp đơn giản nhất sẽ là:

Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;
 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.