最近开发的一个项目中用到了无限级别菜单,因此将此代码贴出来,以供研究,开发环境为VS2008+SQL 2000。
首先,创建数据库表的代码如下:
无限级树的数据库表代码
if
exists
(
select
*
from
dbo.sysobjects
where
id
=
object_id
(N
'
[dbo].[work_sysmenu]
'
)
and
OBJECTPROPERTY
(id, N
'
IsUserTable
'
)
=
1
)
drop table [ dbo ] . [ work_sysmenu ]
GO
CREATE TABLE [ dbo ] . [ work_sysmenu ] (
[ flowid ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL ,
[ menu_title ] [ varchar ] ( 100 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_value ] [ varchar ] ( 100 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_url ] [ varchar ] ( 500 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_parent ] [ int ] NULL ,
[ menu_role ] [ varchar ] ( 200 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_meno ] [ text ] COLLATE Chinese_PRC_CI_AS NULL ,
[ isvalid ] [ int ] NULL ,
[ menu_order ] [ int ] NULL
) ON [ PRIMARY ] TEXTIMAGE_ON [ PRIMARY ]
GO
drop table [ dbo ] . [ work_sysmenu ]
GO
CREATE TABLE [ dbo ] . [ work_sysmenu ] (
[ flowid ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL ,
[ menu_title ] [ varchar ] ( 100 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_value ] [ varchar ] ( 100 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_url ] [ varchar ] ( 500 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_parent ] [ int ] NULL ,
[ menu_role ] [ varchar ] ( 200 ) COLLATE Chinese_PRC_CI_AS NULL ,
[ menu_meno ] [ text ] COLLATE Chinese_PRC_CI_AS NULL ,
[ isvalid ] [ int ] NULL ,
[ menu_order ] [ int ] NULL
) ON [ PRIMARY ] TEXTIMAGE_ON [ PRIMARY ]
GO
其中,menu_parent为菜单的级别代码,最顶级为0,其他级别代码为上级菜单的flowid。
ASP.NET中使用导航中的Menu控件作为菜单。
首先需要将级别为0的顶级菜单添加到Menu中,代码如下:
代码
///
<summary>
/// 根据用户权限获取系统菜单
/// </summary>
private void GetSysMenu()
{
string str = " select * from work_sysmenu where dbo.GetCharCount(menu_role,' " + this .roleid + " ')=1 and isvalid=1 order by menu_order " ;
DataSet ds = sysSqlRunner.getDataset(str);
DataRow[] drRoot = ds.Tables[ 0 ].Select( " menu_parent=0 " );
// 循环生成父菜单
foreach (DataRow dr in drRoot)
{
MenuItem mi = new MenuItem();
mi.Text = dr[ " menu_title " ].ToString();
mi.Value = dr[ " menu_value " ].ToString();
// mi.NavigateUrl = dr["menu_url"].ToString();
mi.Selectable = false ;
mainMenu.Items.Add(mi);
// 递归算法生成所有级别的下级子菜单
CreateMenu(ds.Tables[ 0 ], dr[ " flowid " ].ToString(), mi);
}
}
/// 根据用户权限获取系统菜单
/// </summary>
private void GetSysMenu()
{
string str = " select * from work_sysmenu where dbo.GetCharCount(menu_role,' " + this .roleid + " ')=1 and isvalid=1 order by menu_order " ;
DataSet ds = sysSqlRunner.getDataset(str);
DataRow[] drRoot = ds.Tables[ 0 ].Select( " menu_parent=0 " );
// 循环生成父菜单
foreach (DataRow dr in drRoot)
{
MenuItem mi = new MenuItem();
mi.Text = dr[ " menu_title " ].ToString();
mi.Value = dr[ " menu_value " ].ToString();
// mi.NavigateUrl = dr["menu_url"].ToString();
mi.Selectable = false ;
mainMenu.Items.Add(mi);
// 递归算法生成所有级别的下级子菜单
CreateMenu(ds.Tables[ 0 ], dr[ " flowid " ].ToString(), mi);
}
}
上面的代码中的sysSqlRunner.getDataset是我自用的一个数据持久层框架内的方法,用来执行一段SQL并返回Dataset,这个可以根据自己的需要来使用不同的方法。另外有一条SQL语句中包含一个我自己写的自定义函数dbo.GetCharCount,作用是获取一个字符串中,某个字符存在的个数。
代码
下面为生成下级无级树的方法代码:
代码
///
<summary>
/// 创建无级树菜单
/// </summary>
/// <param name="dt"> 获取菜单的数据源 </param>
/// <param name="parentID"> 菜单的父ID </param>
/// <param name="parItem"> 创建菜单的Item </param>
private void CreateMenu(DataTable dt, string parentID,MenuItem parItem)
{
DataRow[] drs = dt.Select( " menu_parent= " + parentID);
if (drs.Length > 0 )
{
foreach (DataRow dr in drs)
{
MenuItem mi = new MenuItem();
mi.Text = dr[ " menu_title " ].ToString();
mi.Value = dr[ " menu_value " ].ToString();
mi.NavigateUrl = dr[ " menu_url " ].ToString();
parItem.ChildItems.Add(mi);
CreateMenu(dt, dr[ " flowid " ].ToString(), mi);
}
}
else
{
return ;
}
}
/// 创建无级树菜单
/// </summary>
/// <param name="dt"> 获取菜单的数据源 </param>
/// <param name="parentID"> 菜单的父ID </param>
/// <param name="parItem"> 创建菜单的Item </param>
private void CreateMenu(DataTable dt, string parentID,MenuItem parItem)
{
DataRow[] drs = dt.Select( " menu_parent= " + parentID);
if (drs.Length > 0 )
{
foreach (DataRow dr in drs)
{
MenuItem mi = new MenuItem();
mi.Text = dr[ " menu_title " ].ToString();
mi.Value = dr[ " menu_value " ].ToString();
mi.NavigateUrl = dr[ " menu_url " ].ToString();
parItem.ChildItems.Add(mi);
CreateMenu(dt, dr[ " flowid " ].ToString(), mi);
}
}
else
{
return ;
}
}
好了,现在只需要在数据表中添加菜单记录,即可生成所需级别的菜单。需要注意的是顶级菜单的menu_parent值必须为0。当然也可以在此基础上根据需要做修改。