ABP框架 —动态菜单的生成
abp框架为用户提供了一套导航栏菜单的显示,直接使用就可以。
静态显示:
假设我们有一个这样的主菜单:
- Home
- Role
- User
- Add
- Edit
由上可知,Administration菜单项有两个子菜单项。对应的生成方法如下:
public class TestNavigationProvider : NavigationProvider
{
public override void SetNavigation(INavigationProviderContext context)
{
context.Manager.MainMenu
.AddItem(
new MenuItemDefinition(
"Home",
new LocalizableString("Home", "Test"),
url: "/Home",
icon: "fa fa-tasks"
)
).AddItem(
new MenuItemDefinition(
"Role",
new LocalizableString("Role", "Test"),
url: "/Role",
icon: "fa fa-bar-chart"
)
).AddItem(
new MenuItemDefinition(
"User",
new LocalizableString("User", "Test"),
icon: "fa fa-cogs"
).AddItem(
new MenuItemDefinition(
"Add",
new LocalizableString("Add", "Test"),
url: "/User/Add",
icon: "fa fa-users"
)
).AddItem(
new MenuItemDefinition(
"Edit",
new LocalizableString("Edit", "Test"),
url: "/User/Edit",
icon: "fa fa-star"
)
)
);
}
}
MenuItemDefinition可以有一个唯一的名字,一个用于本地化显示的名字,一个url和一个icon,此外:
- requiredPermissionName 属性可以用来判断用户是否有该菜单的权限
- featureDependency 属性为菜单依赖性
- 还可以定义 customData 和 order
InavigationProviderContext方法能够获取现有的菜单项、添加菜单或菜单项。因此,不同的模块可以添加各自的菜单。
在应用程序中可能有一个或者多个菜单,context.Manager.MainMenu 是默认主菜单的引用。我们可以使用 context.Manager.Menus 属性创建和添加更多的菜单。
注册导航提供器
创建完成导航后,我们应该在ABP的 PreInitialize 配置它:
Configuration.Navigation.Providers.Add();
显示菜单
IUserNavigationManager 可以注入、获取和显示菜单。因此,我们可以在服务器端创建菜单。
Abp自动生成的 javascript API 使得用户能够在客户端获取菜单,对应的方法和对象在命名空间 abp.nav 中。例如,在客户端使用 abp.nav.menus.MainMenu 可以用来获取主菜单。所以我们可以在客户端创建菜单。
动态菜单
参照上面静态菜单的用例,我们可以完成动态菜单的显示
public ReadOnly IRespority<EyMenu> _MenuRespority ; //EyMenu 为菜单实体
public TestNavigationProvider ( IRespority<EyMenu> MenuRespority)
{
_MenuRespority = MenuRespority;
}
public class TestNavigationProvider : NavigationProvider
{
public override void SetNavigation(INavigationProviderContext context)
{
var ParentMenu = _MenuRespority.GetAll(g=>g.ParentId = 0); //获取第一级菜单
ParentMenu.ForEach(g=>{
context.Manager.MainMenu.AddItem(GetChildMenu(g)); //将获取到的所有菜单加入到菜单栏中
});
}
}
private class GetChildMenu(MenuItemDefinition ParentMenu)
{
var childMenu = _MenuRespority.GetAll(g=>g.ParentId = (int)ParentMenu.customData); //获取下一级子菜单
childMenu.ForEach(g=>{
MenuItemDefinition subMenu = CreateMenuItem(g);
ParentMenu.AddItem(g); //将子菜单加入到父菜单的Items中
GetChildMenu(g); //继续寻找下一级子菜单
});
}
private MenuItemDefinition CreateMenuItem(EyMenu menu)
{
//创建菜单
return new MenuItemDefinition{
menu.name,
new LocalizableString(menu.name, "Test"),
url:menu.url,
icon:menu.icon,
customData :menu.id
}
}
后台通过递归不断去数据库寻找菜单并将其加入到菜单栏中,前台界面只需直接使用 abp.nav.menus.MainMenu的数据,不需要再次递归创建