问题 ContextMenuStrip.Owner属性null从嵌套ToolStripMenuItem检索时


我有一个 ContextMenuStrip 设置两个 ToolStripItem秒。第二 ToolStripItem 有两个额外的嵌套 ToolStripItem秒。我将其定义为:

ContextMenuStrip cms = new ContextMenuStrip();
ToolStripMenuItem contextJumpTo = new ToolStripMenuItem();
ToolStripMenuItem contextJumpToHeatmap = new ToolStripMenuItem();
ToolStripMenuItem contextJumpToHeatmapStart = new ToolStripMenuItem();
ToolStripMenuItem contextJumpToHeatmapLast = new ToolStripMenuItem();

cms.Items.AddRange(new ToolStripItem[] { contextJumpTo,
                                         contextJumpToHeatmap});
cms.Size = new System.Drawing.Size(176, 148);

contextJumpTo.Size = new System.Drawing.Size(175, 22);
contextJumpTo.Text = "Jump To (No Heatmapping)";

contextJumpToHeatmap.Size = new System.Drawing.Size(175, 22);
contextJumpToHeatmap.Text = "Jump To (With Heatmapping)";
contextJumpToHeatmap.DropDownItems.AddRange(new ToolStripItem[] { contextJumpToHeatmapStart, 
                                                                  contextJumpToHeatmapLast });

contextJumpToHeatmapStart.Size = new System.Drawing.Size(165, 22);
contextJumpToHeatmapStart.Text = "From Start of File";

contextJumpToHeatmapLast.Size = new System.Drawing.Size(165, 22);
contextJumpToHeatmapLast.Text = "From Last Data Point";

然后,我为三者的点击事件设置了一个事件监听器 ToolStripMenuItem那是我想回应的。以下是方法(我只列出了三种方法中的两种):

void contextJumpTo_Click(object sender, EventArgs e)
{
    // Try to cast the sender to a ToolStripItem 
    ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
    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 
            DataGridView dgv = owner.SourceControl as DataGridView;
            if (dgv != null)
                // DO WORK
        }
    } 
}

void contextJumpToHeatmapStart_Click(object sender, EventArgs e)
{
    // Try to cast the sender to a ToolStripItem 
    ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
    if (menuItem != null)
    {
        // Retrieve the ToolStripItem that owns this ToolStripItem 
        ToolStripMenuItem ownerItem = menuItem.OwnerItem as ToolStripMenuItem;
        if (ownerItem != null)
        {
            // Retrieve the ContextMenuStrip that owns this ToolStripItem 
            ContextMenuStrip owner = ownerItem.Owner as ContextMenuStrip;
            if (owner != null)
            {
                // Get the control that is displaying this context menu 
                DataGridView dgv = owner.SourceControl as DataGridView;
                if (dgv != null)
                    // DO WORK
            }
        }
    }
}

这是我的问题:

我的 contextJumpTo_Click 方法非常好。我们一直到我确定的地方 DataGridView 点击来自,我可以继续。该 contextJumpTo  ToolStripMenuItem 但是,它不是一个嵌套的菜单项 ContextMenuStrip

但我的方法 contextJumpToHeatmapStart_Click 不能正常工作。当我走到我确定的路线时 owner.SourceControlSourceControl 是null,我无法继续。现在我知道了 ToolStripMenuItem 嵌套在我的另一个下面 ContextMenuStrip,但为什么呢 SourceControl 属性突然出现在我身上 ContextMenuStrip

我如何获得 SourceControl 对于嵌套 ToolStripMenuItem 为一个 ContextMenuStrip


11843
2017-08-23 14:55


起源



答案:


我相信这是一个错误。

我试图抓取工具条父项列表以获取ContextStripMenu所有者,该工作正常,但SourceControl属性始终为null。

看起来常见的工作是在上下文菜单的开头设置控件:

private Control menuSource;

cms.Opening += cms_Opening;

void cms_Opening(object sender, CancelEventArgs e) {
  menuSource = ((ContextMenuStrip)sender).SourceControl;
}

然后你的代码基本上变成了这个:

DataGridView dgv = menuSource as DataGridView;
if (dgv != null) {
  // do work
}

11
2017-08-23 17:13



我已经得出了同样的结论。有点不耐烦,必须为该属性已存在的东西创建一个属性。但我无能为力。 - Michael Mankus
在看到这个答案之前也得出了这个结论......但回想起来,我认为无论如何这样做实际上更好。 - BVernon
我也是这样的。 - Nine Tails
@RussellHorwood我看不到你的代码,但是尝试在开启事件上调试一个调试中断并检查SourceControl属性以查看你得到的内容。 - LarsTech
这就是我做的,是的,那里有空。如何在没有源的情况下打开上下文菜单? - Nine Tails


答案:


我相信这是一个错误。

我试图抓取工具条父项列表以获取ContextStripMenu所有者,该工作正常,但SourceControl属性始终为null。

看起来常见的工作是在上下文菜单的开头设置控件:

private Control menuSource;

cms.Opening += cms_Opening;

void cms_Opening(object sender, CancelEventArgs e) {
  menuSource = ((ContextMenuStrip)sender).SourceControl;
}

然后你的代码基本上变成了这个:

DataGridView dgv = menuSource as DataGridView;
if (dgv != null) {
  // do work
}

11
2017-08-23 17:13



我已经得出了同样的结论。有点不耐烦,必须为该属性已存在的东西创建一个属性。但我无能为力。 - Michael Mankus
在看到这个答案之前也得出了这个结论......但回想起来,我认为无论如何这样做实际上更好。 - BVernon
我也是这样的。 - Nine Tails
@RussellHorwood我看不到你的代码,但是尝试在开启事件上调试一个调试中断并检查SourceControl属性以查看你得到的内容。 - LarsTech
这就是我做的,是的,那里有空。如何在没有源的情况下打开上下文菜单? - Nine Tails