ASP.NET Core MVC / Razor Pages UI: 导航菜单
每个应用程序都有一个主菜单,允许用户导航到应用程序的页面/屏幕。有些应用程序可能在不同的 UI 部分包含多个菜单。
ABP 是一个模块化应用程序开发框架。每个模块都可能需要向菜单添加项目。
因此,ABP提供了一个菜单基础设施,其中:
- 应用程序或模块可以向菜单添加项目,而无需知道菜单是如何呈现的。
- 主题正确呈现菜单。
添加菜单项
为了添加菜单项(或操作现有项目),您需要创建一个实现 IMenuContributor 接口的类。
应用程序启动模板 已经包含了一个
IMenuContributor的实现。因此,您可以在该类中添加项目,而不是创建一个新的。
示例:添加一个包含 Customers 和 Orders 子菜单项的 CRM 菜单项
using System.Threading.Tasks;
using MyProject.Localization;
using Volo.Abp.UI.Navigation;
namespace MyProject.Web.Menus
{
public class MyProjectMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name == StandardMenus.Main)
{
await ConfigureMainMenuAsync(context);
}
}
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
var l = context.GetLocalizer<MyProjectResource>();
context.Menu.AddItem(
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"])
.AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Customers",
displayName: l["Menu:Customers"],
url: "/crm/customers")
).AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Orders",
displayName: l["Menu:Orders"],
url: "/crm/orders")
)
);
}
}
}
- 此示例仅向主菜单(
StandardMenus.Main:请参阅下面的 标准菜单 部分)添加项目。 - 它从
context获取IStringLocalizer来本地化菜单项的显示名称。 - 将 Customers 和 Orders 作为 CRM 菜单的子项添加。
创建菜单贡献者后,您需要将其添加到模块的 ConfigureServices 方法中的 AbpNavigationOptions:
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new MyProjectMenuContributor());
});
此示例使用了一些本地化键作为显示名称,这些键应在本地化文件中定义:
"Menu:CRM": "CRM",
"Menu:Orders": "订单",
"Menu:Customers": "客户"
有关本地化的更多信息,请参阅本地化文档。
运行应用程序时,您将看到添加到主菜单的项目:
菜单由当前 UI 主题呈现。因此,根据您的主题,主菜单的外观可能完全不同。
这里有一些关于菜单贡献者的说明:
- ABP在需要呈现菜单时调用
ConfigureMenuAsync方法。 - 每个菜单项都可以有子项。因此,您可以添加具有无限深度的菜单项(但是,您的 UI 主题可能不支持无限深度)。
- 通常只有叶菜单项有
url。当您单击父菜单时,其子菜单会打开或关闭,您不会导航到父菜单项的url。 - 如果一个菜单项没有子项且未定义
url,则它不会在 UI 上呈现。这简化了菜单项的授权:您只需授权子项(请参阅下一节)。如果没有子项被授权,则父项会自动消失。
菜单项属性
菜单项有更多选项(ApplicationMenuItem 类的构造函数)。以下是所有可用选项的列表:
name(string,必需):菜单项的唯一名称。displayName(string,必需):菜单项的显示名称/文本。您可以像之前所示那样本地化它。url(string):菜单项的 URL。icon(string):图标名称。开箱即用支持免费的 Font Awesome 图标类。例如:fa fa-book。只要您将必要的 CSS 文件包含到应用程序中,就可以使用任何 CSS 字体图标类。order(int):菜单项的顺序。默认值为1000。除非指定顺序值,否则项目按添加顺序排序。customData(Dictionary<string, object>):一个字典,允许存储自定义对象,您可以将其与菜单项关联并在呈现菜单项时使用它。target(string):菜单项的目标。对于 Web 应用程序,可以是null(默认)、"_blank"、"_self"、"_parent"、"_top" 或框架名称。elementId(string):可用于使用特定的 HTMLid属性呈现元素。cssClass(string):菜单项的附加字符串类。groupName(string):可用于对菜单项进行分组。
授权
如上所述,菜单贡献者动态地向菜单贡献项目。因此,您可以执行任何自定义逻辑或从任何源获取菜单项。
一个用例是授权。您通常希望通过检查权限来添加菜单项。
示例:检查当前用户是否具有权限
if (await context.IsGrantedAsync("MyPermissionName"))
{
//...添加菜单项
}
对于授权,您可以使用 RequirePermissions 扩展方法作为快捷方式。它的性能也更高,ABP 为所有项目优化了权限检查。
context.Menu.AddItem(
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"])
.AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Customers",
displayName: l["Menu:Customers"],
url: "/crm/customers")
.RequirePermissions("MyProject.Crm.Customers")
).AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Orders",
displayName: l["Menu:Orders"],
url: "/crm/orders")
.RequirePermissions("MyProject.Crm.Orders")
)
);
您可以使用
context.AuthorizationService直接访问IAuthorizationService。
解析依赖项
context.ServiceProvider 可用于解析任何服务依赖项。
示例:获取服务
var myService = context.ServiceProvider.GetRequiredService<IMyService>();
//...使用服务
您无需关心释放/处理服务。ABP 会处理它。
管理菜单
菜单中有一个由 ABP 添加的特殊菜单项:管理 菜单。它通常由预构建的管理 应用程序模块 使用:
如果要在 管理 菜单项下添加菜单项,可以使用 context.Menu.GetAdministration() 扩展方法:
context.Menu.GetAdministration().AddItem(...)
操作现有菜单项
ABP 按模块依赖顺序执行菜单贡献者。因此,您可以操作您的应用程序或模块(直接或间接)依赖的菜单项。
示例:为 Identity Module 添加的 Users 菜单项设置图标
var userMenu = context.Menu.FindMenuItem(IdentityMenuNames.Users);
userMenu.Icon = "fa fa-users";
context.Menu使您能够访问先前菜单贡献者添加的所有菜单项。
菜单组
您可以定义组并将菜单项与组关联。
示例:
using System.Threading.Tasks;
using MyProject.Localization;
using Volo.Abp.UI.Navigation;
namespace MyProject.Web.Menus
{
public class MyProjectMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name == StandardMenus.Main)
{
await ConfigureMainMenuAsync(context);
}
}
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
var l = context.GetLocalizer<MyProjectResource>();
context.Menu.AddGroup(
new ApplicationMenuGroup(
name: "Main",
displayName: l["Main"]
)
);
context.Menu.AddItem(
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"], groupName: "Main")
.AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Customers",
displayName: l["Menu:Customers"],
url: "/crm/customers")
).AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Orders",
displayName: l["Menu:Orders"],
url: "/crm/orders")
)
);
}
}
}
UI 主题将决定是否呈现组,如果决定呈现,则呈现方式由主题决定。只有 LeptonX 主题实现了菜单组。
标准菜单
菜单是一个命名的组件。一个应用程序可能包含多个具有不同、唯一名称的菜单。有两个预定义的标准菜单:
Main:应用程序的主菜单。包含指向应用程序页面的链接。定义为常量:Volo.Abp.UI.Navigation.StandardMenus.Main。User:用户个人资料菜单。定义为常量:Volo.Abp.UI.Navigation.StandardMenus.User。
上面已经介绍了 Main 菜单。当用户登录时,User 菜单可用:
您可以通过检查 context.Menu.Name 来向 User 菜单添加项目,如下所示:
if (context.Menu.Name == StandardMenus.User)
{
//...添加项目
}
IMenuManager
IMenuManager 通常由 UI 主题用于在 UI 上呈现菜单项。因此,您通常不需要直接使用 IMenuManager。
示例:获取 Main 菜单项
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Abp.UI.Navigation;
namespace MyProject.Web.Pages
{
public class IndexModel : PageModel
{
private readonly IMenuManager _menuManager;
public IndexModel(IMenuManager menuManager)
{
_menuManager = menuManager;
}
public async Task OnGetAsync()
{
var mainMenu = await _menuManager.GetAsync(StandardMenus.Main);
foreach (var menuItem in mainMenu.Items)
{
//...
}
}
}
}
抠丁客





