项目

本文档有多个版本。请选择最适合您的选项。

UI
Database

Web 应用程序开发教程 - 第 2 部分:书籍列表页面

本地化

在开始 UI 开发之前,我们首先需要准备本地化文本(通常是在开发应用程序时按需进行)。

本地化文本位于 Acme.BookStore.Domain.Shared 项目的 Localization/BookStore 文件夹下:

bookstore-localization-files

打开 en.json 文件(英文翻译),并按以下内容修改:

{
  "Culture": "en",
  "Texts": {
    "Menu:Home": "首页",
    "Welcome": "欢迎",
    "LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 的启动项目。更多信息请访问 abp.io。",
    "Menu:BookStore": "书店",
    "Menu:Books": "书籍",
    "Actions": "操作",
    "Close": "关闭",
    "Delete": "删除",
    "Edit": "编辑",
    "PublishDate": "出版日期",
    "NewBook": "新书",
    "Name": "名称",
    "Type": "类型",
    "Price": "价格",
    "CreationTime": "创建时间",
    "AreYouSure": "确定吗?",
    "AreYouSureToDelete": "确定要删除此项吗?",
    "Enum:BookType.0": "未定义",
    "Enum:BookType.1": "冒险",
    "Enum:BookType.2": "传记",
    "Enum:BookType.3": "反乌托邦",
    "Enum:BookType.4": "奇幻",
    "Enum:BookType.5": "恐怖",
    "Enum:BookType.6": "科学",
    "Enum:BookType.7": "科幻",
    "Enum:BookType.8": "诗歌"
  }
}
  • 本地化键名是任意的,你可以设置任何名称。我们针对特定文本类型推荐一些约定:
    • 为菜单项添加 Menu: 前缀。
    • 使用 Enum:<枚举类型>.<枚举值><枚举类型>.<枚举值> 命名约定来本地化枚举成员。这样处理后,ABP 可以在某些适当场景下自动对枚举进行本地化。

如果本地化文件中未定义某个文本,它将回退到本地化键(遵循 ASP.NET Core 的标准行为)。

ABP 的本地化系统基于 ASP.NET Core 的标准本地化系统构建,并在许多方面进行了扩展。详情请参阅本地化文档

创建书籍页面

是时候创建一些可见且可用的内容了!右键点击 Acme.BookStore.Blazor 项目下的 Pages 文件夹,添加一个新的 razor 组件,命名为 Books.razor

blazor-add-books-component

将此组件的内容替换为以下内容:

@page "/books"

<h2>书籍</h2>

@code {

}

将书籍页面添加到主菜单

打开 Acme.BookStore.Blazor 项目中的 BookStoreMenuContributor 类,并在 ConfigureMainMenuAsync 方法的末尾添加以下代码:

context.Menu.AddItem(
    new ApplicationMenuItem(
        "BooksStore",
        l["Menu:BookStore"],
        icon: "fa fa-book"
    ).AddItem(
        new ApplicationMenuItem(
            "BooksStore.Books",
            l["Menu:Books"],
            url: "/books"
        )
    )
);

运行项目,使用用户名 admin 和密码 1q2w3E* 登录应用程序,你将看到新的菜单项已添加到主菜单:

blazor-menu-bookstore

当你点击 书店 父菜单下的 Books 菜单项时,将被重定向到新的空书籍页面。

书籍列表

我们将使用 Blazorise 库 作为 UI 组件套件。这是一个非常强大的库,支持主要的 HTML/CSS 框架,包括 Bootstrap。

ABP 提供了一个通用的基类 - AbpCrudPageBase<...>,用于创建 CRUD 风格的页面。此基类与用于构建 IBookAppServiceICrudAppService 兼容。因此,我们可以继承 AbpCrudPageBase 来自动化标准 CRUD 操作的后台代码。

打开 Books.razor 并将内容替换为以下内容:

@page "/books"
@using Volo.Abp.Application.Dtos
@using Acme.BookStore.Books
@using Acme.BookStore.Localization
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>

<Card>
    <CardHeader>
        <h2>@L["Books"]</h2>
    </CardHeader>
    <CardBody>
        <DataGrid TItem="BookDto"
                  Data="Entities"
                  ReadData="OnDataGridReadAsync"
                  TotalItems="TotalCount"
                  ShowPager="true"
                  PageSize="PageSize">
            <DataGridColumns>
                <DataGridColumn TItem="BookDto"
                                Field="@nameof(BookDto.Name)"
                                Caption="@L["Name"]"></DataGridColumn>
                <DataGridColumn TItem="BookDto"
                                Field="@nameof(BookDto.Type)"
                                Caption="@L["Type"]">
                    <DisplayTemplate>
                        @L[$"Enum:BookType.{context.Type}"]
                    </DisplayTemplate>
                </DataGridColumn>
                <DataGridColumn TItem="BookDto"
                                Field="@nameof(BookDto.PublishDate)"
                                Caption="@L["PublishDate"]">
                    <DisplayTemplate>
                        @context.PublishDate.ToShortDateString()
                    </DisplayTemplate>
                </DataGridColumn>
                <DataGridColumn TItem="BookDto"
                                Field="@nameof(BookDto.Price)"
                                Caption="@L["Price"]">
                </DataGridColumn>
                <DataGridColumn TItem="BookDto"
                                Field="@nameof(BookDto.CreationTime)"
                                Caption="@L["CreationTime"]">
                    <DisplayTemplate>
                        @context.CreationTime.ToLongDateString()
                    </DisplayTemplate>
                </DataGridColumn>
            </DataGridColumns>
        </DataGrid>
    </CardBody>
</Card>

@code
{
    public Books() // 构造函数
    {
        LocalizationResource = typeof(BookStoreResource);
    }
}

如果你看到一些语法错误,但应用程序能够正确构建和运行,可以暂时忽略它们。Visual Studio 在处理 Blazor 时仍有一些 bug。

  • 继承自 AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>,该基类为我们实现了所有 CRUD 细节。
  • EntitiesTotalCountPageSizeOnDataGridReadAsync 在基类中已定义。
  • LocalizationResource 设置为 BookStoreResource 以本地化文本。

虽然上述代码相当容易理解,但为了更好地理解它们,你可以查阅 Blazorise 的 CardDataGrid 文档。

关于 AbpCrudPageBase

我们将在书籍页面中继续利用 AbpCrudPageBase。你也可以直接注入 IBookAppService 并自行执行所有服务器端调用(这得益于 ABP 的动态 C# HTTP API 客户端代理系统)。为了演示如何在你的 Blazor 应用程序中调用服务器端 HTTP API,我们将在作者页面中手动操作。

运行最终应用程序

现在你可以运行应用程序了!本部分的最终 UI 如下所示:

blazor-bookstore-book-list

这是一个功能完整、服务器端分页、排序和本地化的书籍表格。

在本文档中