2011-12-06 74 views
4

有没有办法显示一个ContextMenu并阻止进一步的执行,直到一个项目被选中?特别是,我想要获得类似于ShowDialog()的行为,但要获得ContextMenu的行为。有没有办法显示“阻塞”WinForms的ContextMenu?

的直接方法行不通:

ContextMenu cm = new ContextMenu(); 
cm.MenuItems.Add("1", (s,e) => {value = 1;}); 
cm.Show(control, location); 

因为Click回调不从Show()直接调用,而是在当消息循环处理click事件之后的一些点。

如果你不走运,menu在处理事件之前就会被垃圾收集,在这种情况下,事件就会悄无声息地丢失。 (意思是这样,你不能真正使用局部变量为ContextMenu秒)

这似乎是工作,但感觉“不干净”:

using (ContextMenu cm = new ContextMenu()) { 
    cm.MenuItems.Add("1", (s,e) => {value = 1;}); 
    cm.Show(control, location); 
    Application.DoEvents(); 
} 

有没有更好的办法?

+1

将您现有的Show()调用后的任何代码移动到Collapse事件的事件处理函数中。或者使用一个窗体,这样你可以使用ShowDialog。 –

回答

0

在仍显示ContextMenu的同时,您可以轻松地阻止垃圾回收。

问题是您正在使用lambda作为菜单项的事件处理程序。这是一个匿名方法,因此它本身不附加到任何会导致ContextMenu被引用并保持活动状态的对象实例。向封闭对象添加一个方法,然后创建一个标准的EventHandler。这样,封闭实例的存在将保持ContextMenu的活力。不像C#1.0那么简洁,但它可以解决问题。

1

对不起,第一个问题。这是我试过的。我做了另一个窗体,我放置了上下文菜单和一个计时器。Form2从Form1显示为模态,然后计时器在Form2上显示上下文菜单。

请注意,表单2有一些属性设置:在任务栏中不可见,没有边界,大小应该与上下文菜单的大小相等。

希望这会有所帮助。

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_MouseUp(object sender, MouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Right) 
     { 
      Form2 ctxForm = new Form2(); 
      ctxForm.Location = this.PointToScreen(e.Location); 
      ctxForm.Size = new Size(0, 0); 
      ctxForm.ShowDialog(); 
     } 
    } 



} 


public partial class Form2 : Form 
{ 
    public Form2() 
    { 
     InitializeComponent(); 
    } 

    private void exitToolStripMenuItem_Click(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     //show menu once 
     contextMenuStrip1.Show(this, PointToClient(Location)); 
     contextMenuStrip1.Focus(); 
     timer1.Enabled = false; 
    } 

    private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e) 
    { 
     this.Close(); 
    } 
} 
0

只是等待菜单不可见。

ContextMenu cm = new ContextMenu(); 
cm.MenuItems.Add("1", (s,e) => {value = 1;}); 
cm.Show(control, location); 
while (cm.Visible == true) Application.DoEvents(); 
相关问题