C# 动态加载菜单
各位大虾:在下遇到一个问题 我想让菜单根据不同权限的用户加载不同的菜单项,比如一般用户登陆只有一会基本操作的菜单(只能查看,不能加、改)。
请各位大虾帮助!如果能发一个实例就更好了。
copyblaze@hotmil.com --------------------编程问答-------------------- 先在界面加,然后打开源文件看看,就知道了 --------------------编程问答-------------------- VC#2005枚举主窗口菜单
//在类中使用需要引用
using System.Windows.Forms;
public override System.Data.DataSet ContentList
{
get
{
DataSet dataSet = new DataSet();
DataTable dataTable = dataSet.Tables.Add();
foreach (Form form in Application.OpenForms)
{
if (form.Text.IndexOf("主菜单") != -1)
{
dataTable.Columns.Add("MENUNAME", System.Type.GetType("System.String"));
foreach (ToolStripItem toolStripItem in form.MainMenuStrip.Items)
{
if (toolStripItem.GetType().ToString() == "System.Windows.Forms.ToolStripMenuItem")
{
ToolStripMenuItem menuItem = (ToolStripMenuItem)toolStripItem;
object[] oResult ={ menuItem.Text.Trim() };
dataTable.Rows.Add(oResult);
if (menuItem.DropDownItems.Count > 0)
enumMenu(menuItem.DropDownItems, menuItem.Text.Trim() + "->", dataTable);
}
}
}
}
return dataSet;
}
}
private void enumMenu(ToolStripItemCollection MenuCollection, string MenuPrefix,DataTable DataTable)
{
foreach (ToolStripItem toolStripItem in MenuCollection)
{
if(toolStripItem.GetType().ToString()=="System.Windows.Forms.ToolStripMenuItem")
{
ToolStripMenuItem menuItem = (ToolStripMenuItem)toolStripItem;
object[] oResult ={ MenuPrefix + menuItem.Text.Trim() };
DataTable.Rows.Add(oResult);
if (menuItem.DropDownItems.Count > 0)
enumMenu(menuItem.DropDownItems, MenuPrefix + menuItem.Text.Trim() + "->", DataTable);
}
}
}
以次类推好了
http://blog.sina.com.cn/donghaima
--------------------编程问答-------------------- 借花献佛
private void Form1_Load(object sender, EventArgs e)
{
CreateMenu();
}
/**/
/// <summary>
/// 动态创建菜单
/// </summary>
private void CreateMenu()
{
//定义一个主菜单
MenuStrip mainMenu = new MenuStrip();
DataSet ds = new DataSet();
//从XML中读取数据。数据结构后面详细讲一下。
string strMenuXml = Application.StartupPath.ToString() + @"\..\..\Menu.txt";
strMenuXml = @"C:\Menu.xml";
ds.ReadXml(strMenuXml);
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文件=====================
<?xml version="1.0" encoding="utf-8" ?>
<Menus>
<MenuItem>
<Text>aaa</Text>
<ItemID>1000</ItemID>
<ParentItemID>0</ParentItemID>
<FormName></FormName>
<IsModule>1</IsModule>
<Level>1</Level>
<ImageName>01.bmp</ImageName>
</MenuItem>
<MenuItem>
<Text>bbb</Text>
<ItemID>1100</ItemID>
<ParentItemID>0</ParentItemID>
<FormName></FormName>
<IsModule>1</IsModule>
<Level>1</Level>
<ImageName>16x16_ico_pdf.gif</ImageName>
</MenuItem>
<MenuItem>
<Text>ccc</Text>
<ItemID>100001</ItemID>
<ParentItemID>1000</ParentItemID>
<FormName>frmInputBooks</FormName>
<IsModule>0</IsModule>
<Level>2</Level>
<ImageName>crest16x16.gif</ImageName>
</MenuItem>
<MenuItem>
<Text>ddd</Text>
<ItemID>100002</ItemID>
<ParentItemID>1000</ParentItemID>
<FormName></FormName>
<IsModule>1</IsModule>
<Level>2</Level>
<ImageName>ico16-16.gif</ImageName>
</MenuItem>
<MenuItem>
<Text>eee</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>fff</Text>
<ItemID>10000201</ItemID>
<ParentItemID>100002</ParentItemID>
<FormName></FormName>
<IsModule>1</IsModule>
<Level>3</Level>
<ImageName>ico_tmn_16x16.jpg</ImageName>
</MenuItem>
<MenuItem>
<Text>ggg</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> --------------------编程问答-------------------- Private Sub subInitMenu()
Try
Dim linti As Int16
Dim lDataRow() As DataRow
Dim ldtTmp As DataTable
Dim lobjAllOperation As DataSet
Dim ldrTmp As DataRow
Dim cMainMenu As New MainMenu
Dim lMenuItemTmp As MenuItem
Dim lMenu As Menu
Dim lstrTmp As String
cMainMenu.MenuItems.Clear()
'取所有菜单信息
lobjAllOperation = GetSeriviceData.User.UserManger.GetMenuList(My.Computer.Registry.CurrentUser.GetValue("LGuser")) 'pobjCommon.funcGetAllOperation
ldtTmp = lobjAllOperation.Tables(1)
'加载最上级菜单
lDataRow = ldtTmp.Select("UpOperationName is Null", "Orders")
For Each ldrTmp In lDataRow
cMainMenu.MenuItems.Add(ldrTmp("OperationName") & ldrTmp("ShortCut"))
Next
'加载固定菜单()
cMainMenu.MenuItems.Add("修改密码(&P)", New EventHandler(AddressOf PassWord_Click))
cMainMenu.MenuItems.Add("帮助(&H)")
cMainMenu.MenuItems(cMainMenu.MenuItems.Count - 1).MenuItems.Add("使用帮助(&H)", New EventHandler(AddressOf Help_Click))
cMainMenu.MenuItems(cMainMenu.MenuItems.Count - 1).MenuItems.Add("关于" & pobjCommon.CompanyName & "信息管理系统(&A)", New EventHandler(AddressOf About_Click))
cMainMenu.MenuItems(cMainMenu.MenuItems.Count - 1).MdiList = True
cMainMenu.MenuItems.Add("退出(&Q)", New EventHandler(AddressOf Exit_Click))
'循环加载系统业务二级菜单
For Each lMenu In cMainMenu.MenuItems
lstrTmp = lMenu.ToString
lstrTmp = Mid(lstrTmp, lstrTmp.LastIndexOf(":") + 3)
lstrTmp = Mid(lstrTmp, 1, lstrTmp.IndexOf("("))
lDataRow = ldtTmp.Select("UpOperationName = '" & lstrTmp & "'", "Orders")
For Each ldrTmp In lDataRow
'自动挂取事件
lMenuItemTmp = New MenuItem(ldrTmp("OperationName") & ldrTmp("ShortCut"), New EventHandler(AddressOf menuItem_Click))
'进行权限判断
lMenuItemTmp.Tag = ldrTmp("ModelName") & StrType & ldrTmp("ClassName")
'lMenuItemTmp.Enabled = pobjCommon.funcMenuEnable(ldrTmp("OperationName"))
lMenu.MenuItems.Add(lMenuItemTmp)
Next
Next
'循环加载系统业务易做图菜单
For linti = 0 To cMainMenu.MenuItems.Count - 2
For Each lMenu In cMainMenu.MenuItems(linti).MenuItems
lstrTmp = lMenu.ToString
lstrTmp = Mid(lstrTmp, lstrTmp.LastIndexOf(":") + 3)
lstrTmp = Mid(lstrTmp, 1, lstrTmp.IndexOf("("))
lDataRow = ldtTmp.Select("UpOperationName = '" & lstrTmp & "'", "Orders")
For Each ldrTmp In lDataRow
'自动挂取事件
lMenuItemTmp = New MenuItem(ldrTmp("OperationName") & ldrTmp("ShortCut"), New EventHandler(AddressOf menuItem_Click))
lMenuItemTmp.Tag = ldrTmp("ModelName") & StrType & ldrTmp("ClassName")
'进行权限判断
'lMenuItemTmp.Visible = pobjCommon.funcMenuEnable(ldrTmp("OperationName"))
lMenu.MenuItems.Add(lMenuItemTmp)
Next
Next
Next linti
Me.Menu = cMainMenu
Catch ex As Exception
Throw ex
End Try
End Sub
Protected Sub menuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Try
Dim menu As MenuItem = CType(sender, MenuItem)
subShowFrom(menu.Tag, menu.Text)
Catch ex As SysErrDeal.clsDealException
funcMsg(ex.Message, MsgType.Information)
Catch ex As Exception
pobjErrDeal.subErrDeal(ex)
End Try
End Sub
c#版本也类似,你把定义方法和挂载的模式改下,当然c#可以利用delegate来写更简洁 --------------------编程问答-------------------- C#:
DataRow[] lDataRow = null;
DataTable ldtTemp = null;
DataSet lobjAllOperation;
DataRow ldrTmp;
MainMenu cMainMenu = new MainMenu();
MenuItem lMenuItemTmp;
String lstrTmp = string.Empty;
cMainMenu.MenuItems.Clear();
//lobjAllOperation = GetSeriviceData.User.UserManger.GetMenuList("LGuser")) ;
ldtTemp = lobjAllOperation.Tables[1];
cMainMenu.MenuItems.Add("修改密码(&P)", delegate
{
MessageBox.Show("asdf");
});
cMainMenu.MenuItems.Add("退出(&Q)", delegate { });
foreach(Menu lMenu in cMainMenu.MenuItems)
{
lstrTmp = lMenu.ToString();
lDataRow = ldtTemp.Select("UpOperationName = '" + lstrTmp + "'", "Orders");
foreach(DataRow ldr in lDataRow)
{
lMenuItemTmp = new MenuItem(ldr["OperationName"].ToString());
lMenuItemTmp.Click += delegate(object lsender, EventArgs le)
{
};
lMenuItemTmp.Visible = pobjCommon.funcMenuEnable(ldr["Operation"]);
lMenuItemTmp.Tag = ldr["ModelName"];
lMenu.MenuItems.Add(lMenuItemTmp);
}
}
this.Menu = cMainMenu; --------------------编程问答-------------------- 如果是只能查看,修改之类的。那么的权限要做到按钮级别了。
麻烦楼主去查看些关于权限设计方面的资料。
你应该维护一张权限的列表吧。 --------------------编程问答-------------------- http://blog.csdn.net/JimFire/archive/2007/07/01/1673146.aspx
给分吧,要源码再发。 --------------------编程问答-------------------- 二楼的那个还没达到楼主想要的效果哦。 --------------------编程问答-------------------- 请问如何快速查找菜单呢?为什么我用ContextMenuStrip.items.indexofkey(菜单名称)返回都是-1啊 --------------------编程问答-------------------- 3楼的例子看了很有帮助,帮我解决了一个动态加载菜单的问题 --------------------编程问答-------------------- 我也遇到了这个问题,不过我已经解决了。我是这样做的,很简单:不要想着怎么添加菜单,事件乱七八糟的很难搞。想着怎么削减菜单就行了。如果没有这权限,就让某个菜单项撤退吧。这简单吧?代码不需要了吧? --------------------编程问答-------------------- 不会 帮顶
补充:.NET技术 , C#