博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

WinForm winform动态生成菜单

Posted on 2011-07-26 09:54  codingsilence  阅读(921)  评论(0编辑  收藏  举报

要用到windows form 的MainMenu控件。于是想做成动态生成并且动态梆定事件,在网上找了一下没有发现什么好的方法。于是自己来研究一下。以前是做web form的东西,对windows form还真有点陌生的感觉。还好以前用Delphi也做过类似人功能有一点印象。就是用递归去创建菜单。好了不多说了,下面看代码。
view sourceprint?001 private void frmMain_Load(object sender, EventArgs e) 
002         { 
003             CreateMenu(); 
004         } 
005   
006         /// <summary> 
007         /// 动态创建菜单 
008         /// </summary> 
009         private void CreateMenu() 
010         { 
011             //定义一个主菜单 
012             MenuStrip mainMenu = new MenuStrip(); 
013             DataSet ds = new DataSet(); 
014             //从XML中读取数据。数据结构后面详细讲一下。 
015             ds.ReadXml(@"..\..\Menu.xml"); 
016             DataView dv = ds.Tables[0].DefaultView; 
017             //通过DataView来过滤数据首先得到最顶层的菜单 
018             dv.RowFilter = "ParentItemID=0"; 
019             for(int i=0; i<dv.Count;i++) 
020             { 
021                 //创建一个菜单项 
022                 ToolStripMenuItem topMenu = new ToolStripMenuItem(); 
023                 //给菜单赋Text值。也就是在界面上看到的值。 
024                 topMenu.Text = dv[i]["Text"].ToString(); 
025                 //如果是有下级菜单则通过CreateSubMenu方法来创建下级菜单 
026                 if (Convert.ToInt16(dv[i]["IsModule"]) == 1) 
027                 { 
028                     //以ref的方式将顶层菜单传递参数,因为他可以在赋值后再回传。--也许还有更好的方法^_^. 
029                     CreateSubMenu(ref topMenu, Convert.ToInt32(dv[i]["ItemID"]),ds.Tables[0]); 
030                 } 
031                 //显示应用程序中已打开的 MDI 子窗体列表的菜单项 
032                 mainMenu.MdiWindowListItem = topMenu; 
033                 //将递归附加好的菜单加到菜单根项上。 
034                 mainMenu.Items.Add(topMenu); 
035             } 
036             mainMenu.Dock = DockStyle.Top; 
037             //将窗体的MainMenuStrip梆定为mainMenu. 
038             this.MainMenuStrip = mainMenu; 
039             //这句很重要。如果不写这句菜单将不会出现在主窗体中。 
040             this.Controls.Add(mainMenu); 
041         } 
042   
043         /// <summary> 
044         /// 创建子菜单 
045         /// </summary> 
046         /// <param name="topMenu">父菜单项</param> 
047         /// <param name="ItemID">父菜单的ID</param> 
048         /// <param name="dt">所有菜单数据集</param> 
049         private void CreateSubMenu(ref ToolStripMenuItem topMenu,int ItemID, DataTable dt) 
050         { 
051             DataView dv = new DataView(dt); 
052             //过滤出当前父菜单下在所有子菜单数据(仅为下一层的) 
053             dv.RowFilter = "ParentItemID=" + ItemID.ToString(); 
054               
055             for (int i = 0; i < dv.Count; i++) 
056             { 
057                 //创建子菜单项 
058                 ToolStripMenuItem subMenu = new ToolStripMenuItem(); 
059                 subMenu.Text = dv[i]["Text"].ToString(); 
060                 //如果还有子菜单则继续递归加载。 
061                 if (Convert.ToInt16(dv[i]["IsModule"]) == 1) 
062                 { 
063                     //递归调用 
064                     CreateSubMenu(ref subMenu, Convert.ToInt32(dv[i]["ItemID"]), dt); 
065                 } 
066                 else
067                 { 
068                     //扩展属性可以加任何想要的值。这里用formName属性来加载窗体。 
069                     subMenu.Tag = dv[i]["FormName"].ToString(); 
070                     //给没有子菜单的菜单项加事件。 
071                     subMenu.Click += new EventHandler(subMenu_Click); 
072                 } 
073                 if (dv[i]["ImageName"].ToString().Length > 0) 
074                 { 
075                     //设置菜单项前面的图票为16X16的图片文件。 
076                     Image img = Image.FromFile(@"..\..\Image\"+dv[i]["ImageName"].ToString()); 
077                     subMenu.Image = img; 
078                     subMenu.Image.Tag = dv[i]["ImageName"].ToString(); 
079                 } 
080                 //将菜单加到顶层菜单下。 
081                 topMenu.DropDownItems.Add(subMenu); 
082             } 
083         } 
084   
085         /// <summary> 
086         /// 菜单单击事件 
087         /// </summary> 
088         /// <param name="sender"></param> 
089         /// <param name="e"></param> 
090         void subMenu_Click(object sender, EventArgs e) 
091         { 
092             //tag属性在这里有用到。 
093             string formName = ((ToolStripMenuItem)sender).Tag.ToString(); 
094             CreateFormInstance(formName); 
095         } 
096   
097         /// <summary> 
098         /// 创建form实例。 
099         /// </summary> 
100         /// <param name="formName">form的类名</param> 
101         private void CreateFormInstance(string formName) 
102         { 
103             bool flag = false; 
104             //遍历主窗口上的所有子菜单 
105             for(int i=0;i<this.MdiChildren.Length; i++) 
106             { 
107                 //如果所点的窗口被打开则重新激活 
108                 if (this.MdiChildren[i].Tag.ToString().ToLower() == formName.ToLower()) 
109                 { 
110                     this.MdiChildren[i].Activate(); 
111                     this.MdiChildren[i].Show(); 
112                     this.MdiChildren[i].WindowState = FormWindowState.Normal; 
113                     flag = true; 
114                     break; 
115                 } 
116             } 
117             if (!flag) 
118             { 
119                 //如果不存在则用反射创建form窗体实例。 
120                 Assembly asm = Assembly.Load("Fastyou.BookShop.Win");//程序集名 
121                 object frmObj = asm.CreateInstance("Fastyou.BookShop.Win." + formName);//程序集+form的类名。 
122                 Form frms = (Form)frmObj; 
123                 //tag属性要重新写一次,否则在第二次的时候取不到。原因还不清楚。有知道的望告知。 
124                 frms.Tag = formName.ToString(); 
125                 frms.MdiParent = this; 
126                 frms.Show(); 
127             } 
128         }
 
view sourceprint?01 <?xml version="1.0" encoding="utf-8" ?> 
02 <Menus> 
03     <MenuItem> 
04         <Text>资料管理</Text> 
05         <ItemID>1000</ItemID> 
06         <ParentItemID>0</ParentItemID> 
07         <FormName></FormName> 
08         <IsModule>1</IsModule> 
09         <Level>1</Level> 
10         <ImageName>01.bmp</ImageName> 
11     </MenuItem> 
12     <MenuItem> 
13         <Text>产品管理</Text> 
14         <ItemID>1100</ItemID> 
15         <ParentItemID>0</ParentItemID> 
16         <FormName></FormName> 
17         <IsModule>1</IsModule> 
18         <Level>1</Level> 
19         <ImageName>16x16_ico_pdf.gif</ImageName>         
20     </MenuItem> 
21     <MenuItem> 
22         <Text>进书管理</Text> 
23         <ItemID>100001</ItemID> 
24         <ParentItemID>1000</ParentItemID> 
25         <FormName>frmInputBooks</FormName> 
26         <IsModule>0</IsModule> 
27         <Level>2</Level> 
28         <ImageName>crest16x16.gif</ImageName> 
29     </MenuItem> 
30     <MenuItem> 
31         <Text>买卖管理</Text> 
32         <ItemID>100002</ItemID> 
33         <ParentItemID>1000</ParentItemID> 
34         <FormName></FormName> 
35         <IsModule>1</IsModule> 
36         <Level>2</Level> 
37         <ImageName>ico16-16.gif</ImageName> 
38     </MenuItem> 
39     <MenuItem> 
40         <Text>作业管理</Text> 
41         <ItemID>110001</ItemID> 
42         <ParentItemID>1100</ParentItemID> 
43         <FormName></FormName> 
44         <IsModule>1</IsModule> 
45         <Level>2</Level> 
46         <ImageName>ico_info_16x16_mask.gif</ImageName> 
47     </MenuItem> 
48     <MenuItem> 
49         <Text>买书管理</Text> 
50         <ItemID>10000201</ItemID> 
51         <ParentItemID>100002</ParentItemID> 
52         <FormName></FormName> 
53         <IsModule>1</IsModule> 
54         <Level>3</Level> 
55         <ImageName>ico_tmn_16x16.jpg</ImageName> 
56     </MenuItem> 
57     <MenuItem> 
58         <Text>买sss管理</Text> 
59         <ItemID>1000020101</ItemID> 
60         <ParentItemID>10000201</ParentItemID> 
61         <FormName>frmBuyBook</FormName> 
62         <IsModule>0</IsModule> 
63         <Level>4</Level> 
64         <ImageName>ico16-16.gif</ImageName> 
65     </MenuItem> 
66     <MenuItem> 
67         <Text>dsafasdf</Text> 
68         <ItemID>11000101</ItemID> 
69         <ParentItemID>110001</ParentItemID> 
70         <FormName>frmBuyBook</FormName> 
71         <IsModule>0</IsModule> 
72         <Level>3</Level> 
73         <ImageName>ico16-16.gif</ImageName> 
74     </MenuItem> 
75 </Menus>
下面来说明一下XML文件。
Text:为显示在窗体上的文字,
ItemID:为菜单的ID,
ParentItemID:为此菜单的父菜单ID如果是顶级菜单则为0
FormName:为单击菜单所要显示的窗体类名如果是还有下级菜单的则不要写。
IsModule:是否还有子菜单1有,0没有
Level:菜单所在的层数。目前还没用到。
ImageName:菜单前的图标为16x16的图片文件。
在这里还可以根据自己的需要加其它的属性,也可以写成以数据库的方式。