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