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的图片文件。 在这里还可以根据自己的需要加其它的属性,也可以写成以数据库的方式。 这是我目前用到的功能。我会继续发表我做这个小软件的心得体会。希望对大家有所帮助。
|