ContextMenuStrip'in hangi denetimde kullanıldığını belirleme


85

ContextMenuStripBirkaç farklı liste kutusuna atanmış bir a sahibim . Ne zaman ContextMenuStriptıklandığını anlamaya çalışıyorum ListBox. Aşağıdaki kodu başlangıç ​​olarak denedim ama çalışmıyor. senderDoğru değeri vardır, ama atamak çalıştığınızda menuSubmittedo boş.

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

Herhangi bir yardım harika olur. Teşekkürler.

Aşağıdaki yardımı kullanarak anladım:

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

aradığım çözüm için teşekkürler. aynı sorunu yaşadım. ancak tüm bu ififadeleri iç içe geçirmemenizi ve if (menuItem == null) return;benim gibiyseniz ve onu işleyen kodunuzun fazladan gereksiz 2 seviyeye yerleştirilmesini istemiyorsanız kullanmanızı öneririm .
Shawn Kovac

Yanıtlar:


126

Bir için ContextMenu:

Sorun, senderparametrenin bağlam menüsünün kendisine değil, bağlam menüsündeki tıklanan öğeye işaret etmesidir.

Yine de basit bir düzeltme, çünkü her biri size hangi menü öğesini içerdiğini söyleyecek MenuItembir GetContextMenuyöntem sunarContextMenu .

Kodunuzu şu şekilde değiştirin:

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

Bir için ContextMenuStrip:

A ContextMenuStripyerine a kullanırsanız işleri biraz değiştirir ContextMenu. İki kontrol birbiriyle ilişkili değildir ve birinin örneği diğerinin bir örneğine dönüştürülemez.

Daha önce olduğu gibi, tıklanan öğe yine de senderparametrede döndürülür , bu nedenle ContextMenuStripbu münferit menü öğesine sahip olanı belirlemeniz gerekir . Bunu Ownermülkle yaparsınız . Son olarak, bağlam menüsünü hangi denetimin görüntülediğini belirlemek için SourceControlözelliği kullanacaksınız .

Kodunuzu şu şekilde değiştirin:

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: O zaman yanlış bir şey daha var. Bu kodu üç farklı liste kutusu ile test ettim ve her şey beklendiği gibi çalıştı. Biraz daha repro kodu gönderin.
Cody Grey

2
@ bluefeet: Cevabımdaki kodu güncelledim. Arasında büyük bir fark var ContextMenuve ContextMenuStrip. (Ah, anladığım kadarıyla zaten çözmüşsün. Bir şeyleri kendi başına öğrenmen daha iyi!)
Cody Gray

1
Menüyü yerel bir değişkene açan SourceControl'ü kaydetmek için Opening olayını kullandım ve sonra öğe tıklamalarını işlerken buna başvurdum.
QuickDanger

1
@QuickDanger Evet, SourceControlmaalesef şu anda Clickbir ToolStripItemalt öğenin bir olayı ContextMenuStriptetiklendiğinde geçersiz . Öyle görünüyor ki ContextMenuStripbireyin Closedolayı harekete önce o Clicksoruna neden muhtemelen budur olay; Menü kapatıldıktan sonra mülkün temizlendiğini varsayıyorum.
Nyerguds

1
@CodyGray Aslında, eğer ağaç daha derindeyse, kendi özelliğinde a olan OwnerItembir bulana kadar özellikler zincirinde döngü oluşturmalısınız . Ama az önce söylediğim gibi, işe yaramıyor; bağlam menüsünde boş olacaktır. Yine de yeniden üretemeyeceğinizi söylediniz ... belki de sorun yalnızca bir seviyeden daha derin menülerle ortaya çıkar? Benimki iki alt seviye derinliğindeydi. ToolStripItemContextMenuStripOwnerSourceControl
Nyerguds

4

Eski gönderi, ancak benim gibi birinin karşısına çıkması durumunda:

Bir ContextMenuStrip için yukarıdakiler benim için işe yaramadı, ancak neyin işe yaradığını bulmamı sağladı.

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

Bu bana beklenen kontrolün adını verdi. Doğrulama vb. İle if ifadeleri koyabilirsiniz, sadece konuya ulaşmak için gönderiyorum.


Bu yalnızca çalışır doğrudan bir öğe ContextMenu. Sorun, ItemClickedtıklandığında ateşlenmemesi alt menü öğelerine ; ClickMenüye değil, gönderen olarak öğenin kendisine sahip olduğu kendi olaylarına ihtiyaçları vardır.
Nyerguds

3

Bu kodun herhangi birini çalıştırmakta büyük zorluk yaşadım. Bulabildiğim en basit çözüm bu:

ContextMenuStrip için:

    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

En kolay çözüm şudur:

Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;
 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.