none
如何让ContextMenu不消失? RRS feed

  • 问题

  • 我想在DataGridView添加一个column chooser,方法是用右键菜单来显示所有列名作为子菜单项。现在的问题是点击选中一个菜单项目后菜单就消失了,我想让它不消失以便可以一次点击选择几项子菜单项。请问如何才能停住菜单?
    2012年5月25日 3:33

答案

  • 主要是在contextMenuStrip的Closing关闭前事件中,判断关闭理由CloseReason是否为ItemClicked,如果是,就设置关闭的Cancel=true,来禁止关闭,以便你进行多项等更多操作,这里我写了个小DEMO,可以参考一下。

    测试效果:

    测试代码:

    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add(new DataColumn("ID", typeof(int)));
                dt.Columns.Add(new DataColumn("Name", typeof(string)));
                dt.Columns.Add(new DataColumn("Age", typeof(int)));
    
                DataRow dr = dt.NewRow();
                dr[0] = 1;
                dr[1] = "codeio";
                dr[2] = 22;
                dt.Rows.Add(dr);
    
                dr = dt.NewRow();
                dr[0] = 2;
                dr[1] = "wknight";
                dr[2] = 21;
                dt.Rows.Add(dr);
    
                dataGridView1.DataSource = dt;
    
                dataGridView1.ContextMenuStrip = contextMenuStrip1;
    
                dataGridView1.GotFocus += dataGridView1_GotFocus;
            }
    
            private void dataGridView1_GotFocus(object sender, EventArgs e)
            {
                ToolStripMenuItem tsm = new ToolStripMenuItem("选择显示项");
                tsm.Enabled = false;
    
                ToolStripSeparator tss = new ToolStripSeparator();
    
                contextMenuStrip1.Items.Add(tsm);
                contextMenuStrip1.Items.Add(tss);
    
                for (int i = 0; i < dataGridView1.Columns.Count; i++)
                {
                    ToolStripMenuItem temp = new ToolStripMenuItem(dataGridView1.Columns[i].HeaderText);
                    temp.Checked = dataGridView1.Columns[i].Visible;
                    contextMenuStrip1.Items.Add(temp);
                }
            }
    
            private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
            {
                ToolStripMenuItem tsm = e.ClickedItem as ToolStripMenuItem;
                if (tsm != null)
                {
                    tsm.Checked = !tsm.Checked;
                }
            }
    
            private void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e)
            {
                if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
                {
                    e.Cancel = true;
                }
            }
    
            private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e)
            {
                for (int i = 2; i < contextMenuStrip1.Items.Count; i++)
                {
                    ToolStripMenuItem tsm = contextMenuStrip1.Items[i] as ToolStripMenuItem;
                    if (tsm != null)
                    {
                        dataGridView1.Columns[contextMenuStrip1.Items[i].Text].Visible = tsm.Checked;
                    }
                }
            }
        }
    }

    代码可以放到Form1.cs直接运行,只要你分别拖一个DataGridView和ContextMenuStrip控件到窗体上。

    2012年5月25日 5:00

全部回复

  • 在每个子菜单项的Click事件中再Call 菜单的Show Method.

    contextMenuStrip1.Show();


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2012年5月25日 4:43
  • 主要是在contextMenuStrip的Closing关闭前事件中,判断关闭理由CloseReason是否为ItemClicked,如果是,就设置关闭的Cancel=true,来禁止关闭,以便你进行多项等更多操作,这里我写了个小DEMO,可以参考一下。

    测试效果:

    测试代码:

    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add(new DataColumn("ID", typeof(int)));
                dt.Columns.Add(new DataColumn("Name", typeof(string)));
                dt.Columns.Add(new DataColumn("Age", typeof(int)));
    
                DataRow dr = dt.NewRow();
                dr[0] = 1;
                dr[1] = "codeio";
                dr[2] = 22;
                dt.Rows.Add(dr);
    
                dr = dt.NewRow();
                dr[0] = 2;
                dr[1] = "wknight";
                dr[2] = 21;
                dt.Rows.Add(dr);
    
                dataGridView1.DataSource = dt;
    
                dataGridView1.ContextMenuStrip = contextMenuStrip1;
    
                dataGridView1.GotFocus += dataGridView1_GotFocus;
            }
    
            private void dataGridView1_GotFocus(object sender, EventArgs e)
            {
                ToolStripMenuItem tsm = new ToolStripMenuItem("选择显示项");
                tsm.Enabled = false;
    
                ToolStripSeparator tss = new ToolStripSeparator();
    
                contextMenuStrip1.Items.Add(tsm);
                contextMenuStrip1.Items.Add(tss);
    
                for (int i = 0; i < dataGridView1.Columns.Count; i++)
                {
                    ToolStripMenuItem temp = new ToolStripMenuItem(dataGridView1.Columns[i].HeaderText);
                    temp.Checked = dataGridView1.Columns[i].Visible;
                    contextMenuStrip1.Items.Add(temp);
                }
            }
    
            private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
            {
                ToolStripMenuItem tsm = e.ClickedItem as ToolStripMenuItem;
                if (tsm != null)
                {
                    tsm.Checked = !tsm.Checked;
                }
            }
    
            private void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e)
            {
                if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
                {
                    e.Cancel = true;
                }
            }
    
            private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e)
            {
                for (int i = 2; i < contextMenuStrip1.Items.Count; i++)
                {
                    ToolStripMenuItem tsm = contextMenuStrip1.Items[i] as ToolStripMenuItem;
                    if (tsm != null)
                    {
                        dataGridView1.Columns[contextMenuStrip1.Items[i].Text].Visible = tsm.Checked;
                    }
                }
            }
        }
    }

    代码可以放到Form1.cs直接运行,只要你分别拖一个DataGridView和ContextMenuStrip控件到窗体上。

    2012年5月25日 5:00
  • DEMO的功能是,右键菜单元素显示DataGridView的列名,然后根据多选的结果,设置DataGridView的列的隐藏和显示,右键菜单多选后,关闭的触发是单击菜单元素意外的地方,如Form窗体,,当然,你可以进一步扩展。。。!
    2012年5月25日 5:02
  • 谢谢您们!我正在看汤姆斯杯,明天试试看。
    2012年5月25日 11:34
  • 我试了,正是我想要的,谢谢!不过这还有一个bug:右击显示菜单后,点击一个单元格来编辑,结束编辑后再右击显示菜单,这时菜单会双重显示!(即两份菜单)

    另外乱马客的方法可能太过于简单,我试过了,没有效果,不过还是很感激!

    2012年5月26日 2:28
  • 关于bug,我把GotFocus里的代码改为放在if块里,不知是否符合一般编程实践?

    private void dataGridView1_GotFocus(object sender, EventArgs e)
    {

       if (contextMenuStrip1.Items.Count == 0)

       {

          //GotFocus代码

       }

    }

    2012年5月26日 2:53
  • 至於ContextMenuStrip的元素什麼時候加載,你完全可以根據自己需求來,方法有很多,=.=
    2012年5月27日 5:12