65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET MVC 特殊视图 - 部分视图和布局

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.68/5 (39投票s)

2013年12月21日

CPOL

10分钟阅读

viewsIcon

412267

downloadIcon

13043

有关 ASP.NET MVC 布局和部分视图的详细信息

引言

ASP.NET MVC 包含三个主要部分 - 模型 (Model)、视图 (View) 和控制器 (Controller)。模型代表业务实体或领域对象,并管理视图的状态。控制器负责应用程序逻辑以及模型和视图之间的通信。视图代表用户界面,它接收用户的输入并将其发送给控制器进行进一步处理。在本文中,我将介绍 ASP.NET MVC 中的特殊视图,如部分视图 (Partial Views) 和布局 (Layouts)。

Using the Code

要理解本文,读者应具备 ASP.NET MVC 的一些基本知识。即使您是 ASP.NET MVC 新手,也请放心,只需浏览这些文章,它将为您提供一些 ASP.NET MVC 的基础知识。有关更多信息,您可以参考链接 www.asp.net/mvc,这是 ASP.NET MVC 的官方网站。

在本文中,我将使用“学生管理”应用程序来演示 ASP.NET MVC 的功能。因此,您可以从这个源文件下载它,并参考它以便更好地理解。在开始运行应用程序之前,请阅读源存档中的 NuGet 包配置文档。

以下表格列出了本文中使用的一些辅助方法。ASP.NET MVC 提供了一组丰富的辅助扩展方法,用于生成 HTML 标记或与其相关的元素。ASP.NET Web Forms 应用程序有许多服务器控件来渲染标记,而辅助方法在 ASP.NET MVC 应用程序中则扮演着相同的角色。

辅助方法名称 描述
@Html.ActionLink() 渲染特定于操作的 URL,我们可以在锚标记中使用它来导航到视图。
@Html.Partial() 将指定的部分视图渲染到当前视图中。
@RenderBody() 在布局页面中渲染子视图的内容。
@RenderSection() 渲染命名节的内容。

部分视图 (Partial Views)

部分视图 (Partial Views) 是特殊的视图,用于渲染视图内容的一部分。它类似于 Web Forms 应用程序中的用户控件,因此可以在多个视图中重用。我们可以通过将复杂的标记拆分为一个或多个部分视图来简化它。因此,部分视图提高了 ASP.NET MVC 应用程序中 HTML 标记的可维护性。

HTML 辅助方法提供了一个名为 Html.Partial 的扩展方法来渲染部分视图。下表显示了 Partial 方法的不同重载。

辅助方法名称 描述
@Html.Partial(string partialViewName) 将指定的部分视图内容渲染到引用的视图中。
@Html.Partial(string partialViewName,object model) 将部分视图内容渲染到引用的视图中。Model 参数将模型对象传递给部分视图。
@Html.Partial(string partialViewName, ViewDataDictionary viewData) 将部分视图内容渲染到引用的视图中。ViewData 参数将 ViewData 字典传递给部分视图。
@Html.Partial(string partialViewName,object model, ViewDataDictionary viewData) 将部分视图内容渲染到引用的视图中。Model 参数将模型对象传递,ViewData 参数将 ViewData 字典传递给部分视图。

下一节将解释如何创建和使用部分视图。

  1. 右键单击 Shared 文件夹,然后选择 Add -> View,这将显示 Add View 对话框。

    Add View

    Add View

  2. 将名称输入为 _StudentItem

  3. 将 Template Engine 值保留为默认。

  4. 勾选 Create a strongly typed view,并从 Student Management.Models 命名空间中选择 Student

  5. 勾选 Create as a partial view。现在 Add View 对话框将如下快照所示。

    Add Partial View

  6. 单击 **Add** 按钮。

Visual Studio 将在 Shared 文件夹下创建一个名为 _StudentItem.cshtml 的文件。打开学生索引视图,它包含显示所有学生的标记,其模块类型为 IEnumerable<Student>。在这里,我们将一部分标记移动到部分视图中,并将其链接到索引视图。以下步骤解释了如何做到这一点。

  1. 将以下标记部分移动到 _StudentItem 部分视图。
    <td>
        @Html.DisplayFor(modelItem => item.Name)
    </td>
    
    <td>
        @Html.DisplayFor(modelItem => item.BranchName)
    </td>
    
    <td>
        @Html.DisplayFor(modelItem => item.CourseName)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Gender)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Address)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id = item.StudentId }) |
        @Html.ActionLink("Details", "Details", new { id = item.StudentId }) |
        @Html.ActionLink("Delete", "Delete", new { id = item.StudentId })
    </td>
  2. 查找并替换 modelItemitem 为 model,但操作链接项除外。对于操作链接项,您应该将 item 替换为 Model,而不是 model
  3. 在索引视图中添加 @Html.Partial("_StudentItem",item),其中第一个参数是部分视图的名称,item 是部分视图的模型对象。现在索引视图中的新标记将如下所示。
    @foreach (var item in Model) {
    <tr>
    @Html.Partial("_StudentItem",item)
    </tr>
  4. 构建应用程序并在浏览器中进行测试。输出没有变化,但我们将一部分数据列表标记移到了部分视图中。这是一个解释部分视图概念的简单示例;您可以在各种场景中使用它

    Partial View

布局

布局 (Layout) 是 ASP.NET MVC 中的另一种特殊视图类型,它类似于 ASP.NET Web Forms 中的母版页。布局用于在整个应用程序中保持 UI 元素和主题的一致性。Razor 布局引入了两个新概念,称为 Web 页面主体 (web page body) 和 Web 页面节 (web page section)。Web Body 只是在特定位置渲染引用视图的内容。Web 页面节用于在布局中声明多个节,这些节由引用视图定义。它有两种形式,一种是没有 required 标志,另一种是有 required 标志;默认情况下,required 标志为 true。当 required 标志为 true 时,引用视图必须为特定命名节提供定义。

Web Body 概念使用 @RenderBody 方法在放置它的位置渲染引用视图的内容。当 Razor 调用此方法时,它会执行所有引用视图(嵌套布局和视图)并渲染视图的 HTML 输出。我们不能在同一个布局中使用此方法一次以上。@RenderSection() 用于在布局中声明一个命名节,引用视图使用 @section 块定义内容。@RenderSection() 方法接受两个参数:一个是要渲染的节的名称,另一个是 required 标志;当 required 标志为 true 时,引用视图必须提供定义,否则它是可选的。还有一个名为 IsSectionDefined 的辅助方法,用于从布局检查是否在任何引用视图中为特定命名节提供了定义。

ASP.NET MVC 模板提供了一个默认布局,名为 _Layout.cshtml/.vbhtml,您可以在 Shared 文件夹下找到此文件。默认情况下,所有视图都使用默认布局,如果您在视图中搜索 layout 属性,您将找不到它,但它仍然引用默认布局。_ViewStart.cshtml 实现了这一功能,它将默认布局分配给所有未显式分配布局的视图,并且它将在视图开始之前执行,这是放置所有视图所需的一些通用代码的好地方。

以下步骤将解释如何创建和使用布局

  1. 右键单击 **Shared** 文件夹,然后选择 Add -> View,这将显示 Add View 对话框。

    Add View

  2. 将 View Name 输入为 **_Admin**。
  3. 将 Template Engine 值保留为默认。
  4. 将 Create strongly typed view 和 Create Partial view 保持为未选中状态。
  5. 取消选中 Use a layout or master page。
  6. 单击 Add 按钮。现在 Add View 对话框将如下快照所示。

    Layout

现在将在 shared 文件夹下创建一个名为 **_Admin.cshtml** 的文件。根据需要修改布局内容,但请确保已放置 @RenderBody() @RenderSection() 方法。其中 @RenderBody() 是必需的,而 @RenderSection 是可选的。

对于学生管理后台控制器的布局,我们将使用以下标记

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - Admin</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body id="admin">
        <header>
             <div id="topbar" class="topbar">
                  <div class="float-left">
                      <nav>
                          <ul id="menu">
                              <li>@Html.ActionLink("Home", "Index", "Admin")</li>
                              <li>@Html.ActionLink("Branch", "Index", "Branch")</li>
                              <li>@Html.ActionLink("Course", "Index", "Course")</li>
                              <li>@Html.ActionLink("Student", "Index", "Student")</li>
                          </ul>
                      </nav>
                  </div>
                  <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                </div>
             </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                     <p>© @DateTime.Now.Year - Student Management Company</p>
                </div>
            </div>
        </footer>
        @Scripts.Render("~/bundles/jquery")
         @Scripts.Render("~/bundles/student")
        @RenderSection("scripts", required: false)
    </body>
</html>

现在为 BranchCourseStudent 创建新的控制器,并使用上述新布局。请遵循以下步骤。

  1. 右键单击 controller 文件夹,然后选择 **Add Controller**,这将显示以下对话框来创建控制器。

    Layout

    Layout

  2. 将 Controller Name 输入为 BranchController
  3. 选择 Template 为 MVC with read/ write actions and views with Entity Framework。
  4. StudentManagement.Models 命名空间中选择 Model Class 为 Branch
  5. StudentManagement.Models 命名空间中选择 Data Context Class 为 AdminContext
  6. 单击 Advanced Option Button。

    Layout

  7. 确保 Use a layout or a master page 已勾选。
  8. Shared 文件夹中选择 Layout 为 _Admin.cshtml
  9. 单击 Advanced Option 对话框上的 **OK** 按钮。

    Layout

  10. 单击 Add Controller 对话框上的 Add 按钮。现在 Controller 对话框将如下快照所示。

    Layout

Visual Studio 将在 Controller 和 Views 文件夹下创建以下文件夹和文件。

控制器 (Controller)

  1. BranchController

视图

  1. Branch
    • Create.cshtml
    • Details.cshtml
    • Delete.cshtml
    • Edit.cshtml
    • Index.cshtml

要为 CourseStudent 等其他模块创建控制器,请为每个模块重复以上步骤。

为所有模块创建控制器后,在 _Admin.cshtml 的 header 部分添加以下链接。

@Html.ActionLink("Branch", "Index", "Branch")
@Html.ActionLink("Course", "Index", "Course")
@Html.ActionLink("Student", "Index", "Student")

如果您已经为上述模块拥有视图,那么只需打开所有视图文件,并在每个视图的顶部添加 Layout 属性,值为 ~/Views/Shared/_Admin.cshtml

Layout 属性

Layout = "~/Views/Shared/_Admin.cshtml";

以上一行显式设置了 Layout 属性为新布局,因此默认布局将不适用。如果您仔细观察所有视图内容,一些视图为 Scripts 命名节提供了定义,而另一些视图则没有。但没有视图为 featured 节提供任何定义,因为它的 required 标志设置为 false,因此此节的定义是可选的。Razor @section 标签用于在引用视图中定义特定命名节的定义。

现在我们可以测试带新布局的应用程序了,因此请构建应用程序并导航到 Admin console,然后检查新布局的输出。它看起来将如下快照所示。

Layout

 

嵌套布局

ASP.NET MVC 允许我们创建嵌套布局,通过它您可以为现有布局创建新的子布局。当您想进一步拆分布局时,这将非常有用。一个重要的事情是父标记可以传递给子布局,但命名节(@RenderSection())不会传递。因此,您可能会遇到错误,如无法在子布局中找到 RenderSection。您可以通过在子布局中重新声明所有父节来修复此问题。

以下步骤将展示如何创建和使用嵌套布局

  1. 右键单击 Shared 文件夹,然后选择 Add -> View,这将显示 Add View 对话框。
  2. 将 View Name 输入为 _AdminNestedLayout
  3. 将 Template Engine 值保留为默认。
  4. 将 Create strongly typed view 和 Create Partial view 保持为未选中状态。
  5. 将 Use a layout or master page 选择为 _Admin.cshtml
  6. 单击 Add 按钮。现在 Add View 对话框将如下快照所示。

    Layout

Visual Studio 将在 shared 文件夹下创建一个文件,名为 _AdminNestedLayout.cshtml。它将包含以下内容。

@{
    ViewBag.Title = "_AdminNestedLayout";
    Layout = "~/Views/Shared/_Admin.cshtml";
}
        <h2>_AdminChildLayout</h2>
    

从标记中删除 ViewBag.Title 属性,并用以下内容替换现有内容。

@{
    Layout = "~/Views/Shared/_Admin.cshtml";
}
<h2 class="hr">@ViewBag.Title</h2>
@RenderBody()

此嵌套布局的目的是为所有管理员视图提供唯一的动作标题格式。现在我们需要将此新布局链接到所有管理员视图,请继续并对所有管理员视图的 Layout 属性进行以下修改。

Layout = "~/Views/Shared/_ AdminNestedLayout.cshtml";

在所有管理员视图中, wherever you find the <h2>Action name</h2> markup,请将其删除,并稍微修改您的标题显示方式。现在运行应用程序并检查结果,在索引视图中您不会遇到任何问题,但当您尝试导航到任何模块的 Create New 链接时,您会收到以下错误,

The following sections have been defined but have not been rendered for the layout page "~/Views/Shared/_AdminNestedLayout.cshtml": "Scripts".
    

上述错误表明当前视图中使用的 Script 节未在嵌套布局中声明,父布局 _Admin.cshtml 已经为 Scripts 定义了 @RenderSection,但仍然无法在嵌套布局中识别它。原因是父节不会自动传递给子布局,除非在子/嵌套布局中重新声明这些节。一旦您在 _AdminNestedLayout.cshtml 中重新声明了 scripts 节,上述错误就会消失。以下代码片段显示了在嵌套布局中重新声明 scripts 节。

_AdminNestedLayout.cshtml

@section scripts{
    @RenderSection("scripts",false)
}

我们可以使用 IsSectionDefined 方法来检查引用视图中是否已定义了命名节的定义,使用此方法,我们可以将上述 razor 块更改为以下内容:

<!-- define a named section -->
<!-- Check whether the referencing view has given the definition for this named section -->
@if (IsSectionDefined("Scripts"))
{
    @section scripts{
<!-- re-declare the parent section to extend to referencing view -->        
    @RenderSection("scripts",false)
    }
}

构建并运行应用程序,然后检查结果。它看起来将如下快照所示。

Layout

结论

在本文中,我们讨论了布局和部分视图是什么,如何创建和使用它们。我们还学习了一些在使用它们时应该遵循的重要事项。请在评论部分提供您的宝贵反馈。感谢您花时间阅读本文。我希望它能为您提供一些有用的信息。

 

© . All rights reserved.