Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#DataGridView动态上下文菜单_C#_Datagridview_Contextmenu - Fatal编程技术网

C#DataGridView动态上下文菜单

C#DataGridView动态上下文菜单,c#,datagridview,contextmenu,C#,Datagridview,Contextmenu,我有一个C#DataGridView,它最多显示5个计时器的计时。使用DataGridView MouseClick事件,我能够创建一个动态上下文菜单,其中包含选项“开始计时器”和“停止计时器”。请参阅下面的代码 我遇到的麻烦是将动态上下文菜单链接到一个方法。例如,当选择“启动计时器1”时,我需要它启动第一个计时器,但“启动计时器2”需要启动另一个计时器。我已经有了一个启动相关计时器的方法(与上下文菜单无关),但我不确定如何将两者联系起来 我想我需要一个上下文菜单事件的地方,但我有点迷路了 任何

我有一个C#DataGridView,它最多显示5个计时器的计时。使用DataGridView MouseClick事件,我能够创建一个动态上下文菜单,其中包含选项“开始计时器”和“停止计时器”。请参阅下面的代码

我遇到的麻烦是将动态上下文菜单链接到一个方法。例如,当选择“启动计时器1”时,我需要它启动第一个计时器,但“启动计时器2”需要启动另一个计时器。我已经有了一个启动相关计时器的方法(与上下文菜单无关),但我不确定如何将两者联系起来

我想我需要一个上下文菜单事件的地方,但我有点迷路了

任何帮助都会很有帮助

private void dataGridView1_MouseClick(object sender, MouseEventArgs e) 
{     
   if (e.Button == MouseButtons.Right)     
   {         
      ContextMenu m = new ContextMenu();         

      int r = dataGridView1.HitTest(e.X,e.Y).RowIndex;

      m.MenuItems.Add(new MenuItem("Start Timer " + r.ToString()));         
      m.MenuItems.Add(new MenuItem("Stop Timer " + r.ToString()));         

      m.Show(dataGridView1, new Point(e.X, e.Y));      
   }
}

private void StartTimer(int t)
{
   ... code starts the t timer ...
} 

您可以处理MenuItem。单击如下事件:

var item = new MenuItem("Start Timer " + r.ToString();
item.Click += (sender, e) => this.StartTimer(r);
m.MenuItems.Add(item)

如果要使用MVVM,也可以使用Command和CommandParameters(http://msdn.microsoft.com/en-us/library/ms752308.aspx)

在未能使上述代码正常工作后,我做了更多的研究,现在有了一个粗略的解决方案(见下文)

我将上下文菜单设置为ContextMenuStrip并链接了ItemClick事件。我找不到将“r”变量传递给StartTimer方法的方法,因此我必须将其设置为全局变量,我知道这不是正确的C#方法。我确实尝试过让EventHandler运行一个带有int参数的自定义方法,但它的错误是“methodname Expected”

正如我提到的,我的代码确实有效,但我希望得到更多的建议

private void dataGridView1_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        int r = dataGridView1.HitTest(e.X, e.Y).RowIndex + 1;

        ContextMenuStrip m = new ContextMenuStrip();

        globals.timer = r;

        m.Items.Add("Start");
        m.Items.Add("Stop");
        m.ItemClicked += new ToolStripItemClickedEventHandler(m_ItemClicked);

        m.Show(dataGridView1, new Point(e.X, e.Y));
    }
}

void m_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
    switch (e.ClickedItem.Text)
    {
        case "Start":
            startTimer(globals.timer);
            break;
        case "Stop":
            stopTimer(globals.timer);
            break;
        default:
            break;
    }
}

private void startTimer(int t)
{
    // code here to start timer t
} 

private void stopTimer(int t)
{
    // code here to stop timer t
}

static class globals
{
    public static int timer = 0;
}

谢谢你,尼古拉。我会试试的,尼古拉。我确实尝试了上面的代码,但无法使其工作。我理解它背后的想法,所以我自己发布了一个带有工作版本的答案。虽然非常粗糙。
Item.Click+=(sender,e)=>this.StartTimer(r)是使用lambda函数而不是方法。在lambda函数中,您可以捕获局部变量,如
r
,并访问它们,然后lambda调用,这样您就不需要全局变量。或者,您可以将
r
保存在ContextMenuStrip的属性标记中,并在eventHandlerOk中使用它再次感谢Nikolay。我以前没有遇到过Tags或Lambda,所以我会做一些调查并尝试一下。