惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
GbyAI
GbyAI
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Blog of Author Tim Ferriss
Vercel News
Vercel News
Microsoft Azure Blog
Microsoft Azure Blog
Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
AWS News Blog
AWS News Blog
Spread Privacy
Spread Privacy
Apple Machine Learning Research
Apple Machine Learning Research
L
LINUX DO - 最新话题
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Privacy International News Feed
C
CERT Recently Published Vulnerability Notes
C
Cybersecurity and Infrastructure Security Agency CISA
I
Intezer
Hugging Face - Blog
Hugging Face - Blog
H
Heimdal Security Blog
N
News and Events Feed by Topic
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Troy Hunt's Blog
大猫的无限游戏
大猫的无限游戏
SecWiki News
SecWiki News
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Application and Cybersecurity Blog
Application and Cybersecurity Blog
F
Fortinet All Blogs
Hacker News: Ask HN
Hacker News: Ask HN
Know Your Adversary
Know Your Adversary
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 聂微东
S
Secure Thoughts
云风的 BLOG
云风的 BLOG
O
OpenAI News
The Cloudflare Blog
Jina AI
Jina AI
U
Unit 42
L
Lohrmann on Cybersecurity
Attack and Defense Labs
Attack and Defense Labs
The Register - Security
The Register - Security
G
Google Developers Blog
量子位
Simon Willison's Weblog
Simon Willison's Weblog
V
Visual Studio Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
G
GRAHAM CLULEY
TaoSecurity Blog
TaoSecurity Blog

博客园 - skylai

mvc3 小技巧 WCF学习之旅(一)---Hello World. WCF Client configuration Jquery表单验证 Jquery的一些常用信息 二进制、SOAP的序列化及反序列化 简单的Attribute实现. 泛型之泛型约束 C#泛型之泛型委托 C#2.0泛型介绍之简单泛型类。 序列化之XML序列化(一) 强制字符换行CSS版和C#版 js操作xml 读写XML文件 js的一些杂谈 一个button同时执行多个有返回值的函数的解决方法(return false; or return true;) DataGrid里应用radio单选按钮 限制字符输入(ASCII 码) 前两天刚看书看到的,来这里跟大家分享一下有关C#处理指令的问题
Vs2005的win form动态生成菜单
skylai · 2006-08-15 · via 博客园 - skylai

这几天想用vs2005做点东西。要用到windows form 的MainMenu控件。于是想做成动态生成并且动态梆定事件,在网上找了一下没有发现什么好的方法。于是自己来研究一下。以前是做web form的东西,对windows form还真有点陌生的感觉。还好以前用Delphi也做过类似人功能有一点印象。就是用递归去创建菜单。好了不多说了,下面看代码。


        
private void frmMain_Load(object sender, EventArgs e)
        
{
            CreateMenu();
        }


        
/// <summary>
        
/// 动态创建菜单
        
/// </summary>

        private void CreateMenu()
        
{
            
//定义一个主菜单
            MenuStrip mainMenu = new MenuStrip();
            DataSet ds 
= new DataSet();
            
//从XML中读取数据。数据结构后面详细讲一下。
            ds.ReadXml(@"..\..\Menu.xml");
            DataView dv 
= ds.Tables[0].DefaultView;
            
//通过DataView来过滤数据首先得到最顶层的菜单
            dv.RowFilter = "ParentItemID=0";
            
for(int i=0; i<dv.Count;i++)
            
{
                
//创建一个菜单项
                ToolStripMenuItem topMenu = new ToolStripMenuItem();
                
//给菜单赋Text值。也就是在界面上看到的值。
                topMenu.Text = dv[i]["Text"].ToString();
                
//如果是有下级菜单则通过CreateSubMenu方法来创建下级菜单
                if (Convert.ToInt16(dv[i]["IsModule"]) == 1)
                
{
                    
//以ref的方式将顶层菜单传递参数,因为他可以在赋值后再回传。--也许还有更好的方法^_^.
                    CreateSubMenu(ref topMenu, Convert.ToInt32(dv[i]["ItemID"]),ds.Tables[0]);
                }

                
//显示应用程序中已打开的 MDI 子窗体列表的菜单项
                mainMenu.MdiWindowListItem = topMenu;
                
//将递归附加好的菜单加到菜单根项上。
                mainMenu.Items.Add(topMenu);
            }

            mainMenu.Dock 
= DockStyle.Top;
            
//将窗体的MainMenuStrip梆定为mainMenu.
            this.MainMenuStrip = mainMenu;
            
//这句很重要。如果不写这句菜单将不会出现在主窗体中。
            this.Controls.Add(mainMenu);
        }


        
/// <summary>
        
/// 创建子菜单
        
/// </summary>
        
/// <param name="topMenu">父菜单项</param>
        
/// <param name="ItemID">父菜单的ID</param>
        
/// <param name="dt">所有菜单数据集</param>

        private void CreateSubMenu(ref ToolStripMenuItem topMenu,int ItemID, DataTable dt)
        
{
            DataView dv 
= new DataView(dt);
            
//过滤出当前父菜单下在所有子菜单数据(仅为下一层的)
            dv.RowFilter = "ParentItemID=" + ItemID.ToString();
            
            
for (int i = 0; i < dv.Count; i++)
            
{
                
//创建子菜单项
                ToolStripMenuItem subMenu = new ToolStripMenuItem();
                subMenu.Text 
= dv[i]["Text"].ToString();
                
//如果还有子菜单则继续递归加载。
                if (Convert.ToInt16(dv[i]["IsModule"]) == 1)
                
{
                    
//递归调用
                    CreateSubMenu(ref subMenu, Convert.ToInt32(dv[i]["ItemID"]), dt);
                }

                
else
                
{
                    
//扩展属性可以加任何想要的值。这里用formName属性来加载窗体。
                    subMenu.Tag = dv[i]["FormName"].ToString();
                    
//给没有子菜单的菜单项加事件。
                    subMenu.Click += new EventHandler(subMenu_Click);
                }

                
if (dv[i]["ImageName"].ToString().Length > 0)
                
{
                    
//设置菜单项前面的图票为16X16的图片文件。
                    Image img = Image.FromFile(@"..\..\Image\"+dv[i]["ImageName"].ToString());
                    subMenu.Image 
= img;
                    subMenu.Image.Tag 
= dv[i]["ImageName"].ToString();
                }

                
//将菜单加到顶层菜单下。
                topMenu.DropDownItems.Add(subMenu);
            }

        }


        
/// <summary>
        
/// 菜单单击事件
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        void subMenu_Click(object sender, EventArgs e)
        
{
            
//tag属性在这里有用到。
            string formName = ((ToolStripMenuItem)sender).Tag.ToString();
            CreateFormInstance(formName);
        }


        
/// <summary>
        
/// 创建form实例。
        
/// </summary>
        
/// <param name="formName">form的类名</param>

        private void CreateFormInstance(string formName)
        
{
            
bool flag = false;
            
//遍历主窗口上的所有子菜单
            for(int i=0;i<this.MdiChildren.Length; i++)
            
{
                
//如果所点的窗口被打开则重新激活
                if (this.MdiChildren[i].Tag.ToString().ToLower() == formName.ToLower())
                
{
                    
this.MdiChildren[i].Activate();
                    
this.MdiChildren[i].Show();
                    
this.MdiChildren[i].WindowState = FormWindowState.Normal;
                    flag 
= true;
                    
break;
                }

            }

            
if (!flag)
            
{
                
//如果不存在则用反射创建form窗体实例。
                Assembly asm = Assembly.Load("Fastyou.BookShop.Win");//程序集名
                object frmObj = asm.CreateInstance("Fastyou.BookShop.Win." + formName);//程序集+form的类名。
                Form frms = (Form)frmObj;
                
//tag属性要重新写一次,否则在第二次的时候取不到。原因还不清楚。有知道的望告知。
                frms.Tag = formName.ToString();
                frms.MdiParent 
= this;
                frms.Show();
            }

        }

<?xml version="1.0" encoding="utf-8" ?>
<Menus>
    
<MenuItem>
        
<Text>资料管理</Text>
        
<ItemID>1000</ItemID>
        
<ParentItemID>0</ParentItemID>
        
<FormName></FormName>
        
<IsModule>1</IsModule>
        
<Level>1</Level>
        
<ImageName>01.bmp</ImageName>
    
</MenuItem>
    
<MenuItem>
        
<Text>产品管理</Text>
        
<ItemID>1100</ItemID>
        
<ParentItemID>0</ParentItemID>
        
<FormName></FormName>
        
<IsModule>1</IsModule>
        
<Level>1</Level>
        
<ImageName>16x16_ico_pdf.gif</ImageName>        
    
</MenuItem>
    
<MenuItem>
        
<Text>进书管理</Text>
        
<ItemID>100001</ItemID>
        
<ParentItemID>1000</ParentItemID>
        
<FormName>frmInputBooks</FormName>
        
<IsModule>0</IsModule>
        
<Level>2</Level>
        
<ImageName>crest16x16.gif</ImageName>
    
</MenuItem>
    
<MenuItem>
        
<Text>买卖管理</Text>
        
<ItemID>100002</ItemID>
        
<ParentItemID>1000</ParentItemID>
        
<FormName></FormName>
        
<IsModule>1</IsModule>
        
<Level>2</Level>
        
<ImageName>ico16-16.gif</ImageName>
    
</MenuItem>
    
<MenuItem>
        
<Text>作业管理</Text>
        
<ItemID>110001</ItemID>
        
<ParentItemID>1100</ParentItemID>
        
<FormName></FormName>
        
<IsModule>1</IsModule>
        
<Level>2</Level>
        
<ImageName>ico_info_16x16_mask.gif</ImageName>
    
</MenuItem>
    
<MenuItem>
        
<Text>买书管理</Text>
        
<ItemID>10000201</ItemID>
        
<ParentItemID>100002</ParentItemID>
        
<FormName></FormName>
        
<IsModule>1</IsModule>
        
<Level>3</Level>
        
<ImageName>ico_tmn_16x16.jpg</ImageName>
    
</MenuItem>
    
<MenuItem>
        
<Text>买sss管理</Text>
        
<ItemID>1000020101</ItemID>
        
<ParentItemID>10000201</ParentItemID>
        
<FormName>frmBuyBook</FormName>
        
<IsModule>0</IsModule>
        
<Level>4</Level>
        
<ImageName>ico16-16.gif</ImageName>
    
</MenuItem>
    
<MenuItem>
        
<Text>dsafasdf</Text>
        
<ItemID>11000101</ItemID>
        
<ParentItemID>110001</ParentItemID>
        
<FormName>frmBuyBook</FormName>
        
<IsModule>0</IsModule>
        
<Level>3</Level>
        
<ImageName>ico16-16.gif</ImageName>
    
</MenuItem>
</Menus>

下面来说明一下XML文件。
Text:为显示在窗体上的文字,
ItemID:为菜单的ID,
ParentItemID:为此菜单的父菜单ID如果是顶级菜单则为0
FormName:为单击菜单所要显示的窗体类名如果是还有下级菜单的则不要写。
IsModule:是否还有子菜单1有,0没有
Level:菜单所在的层数。目前还没用到。
ImageName:菜单前的图标为16x16的图片文件。
在这里还可以根据自己的需要加其它的属性,也可以写成以数据库的方式。
这是我目前用到的功能。我会继续发表我做这个小软件的心得体会。希望对大家有所帮助。