ContextMenuStrip이 사용 된 컨트롤 확인


84

나는 ContextMenuStrip여러 다른 목록 상자에 할당되어 있습니다. 나는 그것이 사용 된 ContextMenuStrip것을 클릭 했을 때 알아 내려고 노력하고 ListBox있습니다. 아래 코드를 시작으로 시도했지만 작동하지 않습니다. 는 sender올바른 값을 가지고,하지만 난에 할당 할 때 menuSubmitted그것은 null입니다.

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

어떤 도움이라도 좋을 것입니다. 감사.

아래 도움을 사용하여 알아 냈습니다.

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;
                }
            }
        }

내가 찾고 있던 해결책에 감사드립니다. 나는 같은 문제가 있었다. 그러나 나는 모든 if문을 중첩 if (menuItem == null) return;하지 않고 당신이 나와 같고 그것을 처리하는 코드가 불필요한 2 레벨 중첩되기를 원하지 않는 경우 사용 하는 것이 좋습니다 .
Shawn Kovac 2013

답변:


123

의 경우 ContextMenu:

문제는 sender매개 변수 가 컨텍스트 메뉴 자체가 아니라 클릭 된 컨텍스트 메뉴 의 항목 을 가리키는 것입니다.

그러나 각각 MenuItem은 해당 메뉴 항목 을 포함 하는 GetContextMenu메서드 를 표시 하기 때문에 간단한 수정 ContextMenu입니다.

코드를 다음과 같이 변경하십시오.

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;
    }
}

의 경우 ContextMenuStrip:

대신를 사용하면 약간 변경 ContextMenuStrip됩니다 ContextMenu. 두 컨트롤은 서로 관련이 없으며 하나의 인스턴스를 다른 하나의 인스턴스로 캐스팅 할 수 없습니다.

이전과 마찬가지로 클릭 한 항목 은 여전히 sender매개 변수에 반환 ContextMenuStrip되므로이 개별 메뉴 항목을 소유 하는을 결정해야 합니다. 당신은 Owner속성으로 그렇게합니다 . 마지막으로이 SourceControl속성 을 사용 하여 상황에 맞는 메뉴를 표시하는 컨트롤을 확인합니다.

다음과 같이 코드를 수정하십시오.

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 : 그렇다면 다른 문제가 있습니다. 세 가지 다른 목록 상자로이 코드를 테스트했는데 모든 것이 예상대로 작동했습니다. 재현 코드를 더 게시하십시오.
Cody Gray

2
@bluefeet : 내 대답의 코드를 업데이트했습니다. ContextMenu와 사이에는 큰 차이가 ContextMenuStrip있습니다. (아, 그리고 당신이 이미 알아 낸 것 같군요. 글쎄요, 혼자서 배우는 것이 더 좋습니다!)
Cody Gray

1
Opening 이벤트를 사용하여 메뉴를 연 SourceControl을 로컬 변수에 기록한 다음 항목 클릭을 처리 할 때이를 참조했습니다.
QuickDanger 2017-06-08

1
@QuickDanger 예, 의 하위 항목 이벤트가 발생하는 SourceControl순간 슬프게도 null 입니다. 의 이벤트가 해당 이벤트 이전 에 발생 하는 것 같습니다 . 이로 인해 문제가 발생할 수 있습니다. 메뉴가 '닫힌'후에 속성이 지워진 것으로 가정합니다. ClickToolStripItemContextMenuStripContextMenuStripClosedClick
Nyerguds

1
나무가 깊은 경우 사실, 당신의 체인 최대 루프가 @CodyGray OwnerItem당신이 찾을 때까지 속성 ToolStripItem가 그 ContextMenuStrip자신의 Owner속성을. 하지만 방금 언급했듯이 작동하지 않습니다. SourceControl컨텍스트 메뉴는 null가됩니다. 그래도 재현 할 수 없다고 하셨는데 ... 한 레벨보다 깊은 메뉴에서만 문제가 발생하는 것일까 요? 내 것은 두 개의 하위 수준 깊이였습니다.
Nyerguds

3

이전 게시물이지만 나 같은 사람이 발견 한 경우 :

ContextMenuStrip의 경우 위의 내용이 저에게 효과가 없었지만 그 결과가 무엇인지 찾아 냈습니다.

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

이것은 나에게 예상되는 컨트롤의 이름을 주었다. if 문으로 유효성 검사 등을 넣을 수 있습니다. 요점에 도달하기 위해 게시하고 있습니다.


이것은 단지와 함께 작동 직접 A의 항목 ContextMenu. 문제는 하위 메뉴 항목을ItemClicked 클릭 할 때 실행되지 않는다는 것입니다 . 메뉴가 아니라 항목 자체를 보낸 사람으로하는 자체 이벤트 가 필요 합니다. Click
Nyerguds

3

이 코드를 작동시키는 데 큰 어려움이있었습니다. 이것이 내가 찾을 수있는 가장 간단한 해결책입니다.

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

가장 쉬운 해결책은 다음과 같습니다.

Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;
 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.