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

使用 AJAX 在 ASP.NET MVC 中刷新表格内容 (jQuery DataTables 和 ASP.NET MVC 集成 - 第三部分)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (42投票s)

2011 年 4 月 5 日

CPOL

17分钟阅读

viewsIcon

417878

downloadIcon

11433

如何在 ASP.NET MVC 中使用 jQuery DataTables 插件刷新表格内容

目录

  1. 引言
  2. 背景
  3. Using the Code
    1. 模型
    2. 视图
    3. 控制器 (Controller)
  4. 摘要
  5. 历史

简介

在本文中,我将展示如何通过 AJAX 刷新 HTML 表格内容。如果您使用的是普通的 HTML 表格,重新加载表格并不是一项非常复杂的任务。您所要做的就是向服务器端页面发送一个 AJAX 请求,获取服务器的响应,然后将其放入表格中。我相信您已经做过很多次了。有一个简单的 jQuery 代码可以做到这一点。

$("table#employees tbody").load("TableContent.aspx");

此调用将向服务器端页面 TableContent.aspx 发送一个 AJAX 调用,读取 TableContent.aspx 提供的响应,并将其放入表格的 body 中。在 TableContent.aspx 页面中,您需要返回一个有效的 HTML,代表将放置在表格中的行集。

如果您的表格很简单,可以替换为服务器响应的内容,那么这 funziona 良好。但是,如果您有一些高级功能,例如分页、排序、过滤,事情可能会变得更加复杂。当您向服务器发送请求时,您需要包含有关当前页面和表格状态的信息,并确保您已加载了正确的内容,选择了分页中的正确页码等。如果您有更高级的表格,最好使用一些已经内置了刷新功能的现有组件。

我的选择是 jQuery DataTables 插件。使用 jQuery DataTables 插件,您只需一行 JavaScript 代码即可为普通表格添加分页、过滤和排序功能。

var oEmployeesTable = $('table#employees').dataTable();

本示例使用了一个 ID 为“employees”的普通 HTML 表格,并将 DataTables 插件应用于该表格。此调用将为表格添加分页、排序和过滤功能。

您也可以使用略有不同的调用轻松创建一个完全 AJAX 化的表格。

var oEmployeesTable = $('table#employees').dataTable({
           "bServerSide": true,
           "sAjaxSource": "DataContent.aspx"
});

在这种情况下,设置了两个参数,指定信息将从服务器端页面 DataContent.aspx 而非 HTML 中获取。

如果您使用 DataTables 来刷新表格内容,您将需要执行一行 JavaScript 代码。

oEmployeesTable.fnDraw();

此调用将刷新表格内容。在本文中,我将展示如何在 ASP.NET MVC 应用程序中实现刷新功能。

背景

jQuery DataTables 插件是一个优秀的 jQuery 库,它使您能够以最少的精力创建完全 AJAX 化的表格。要使用 jQuery DataTables 插件创建 AJAX 化的表格,您需要实现以下元素:

  1. 在页面的 HTML 中放置一个空的表格。这个空的表格将定义表格的结构(例如,列、样式等)。表格应只在 THEAD 元素中有一个标题,一个空的 body,以及一个可选的 TFOOT 元素。表格中的行不是必需的,因为它们将通过 AJAX 调用加载。
  2. 创建一个服务器端页面,当通过 AJAX 调用时,该页面将为表格提供行。在本文中,将实现一个 ASP.NET MVC 控制器,它将为表格提供数据行。
  3. 初始化 jQuery DataTables 插件以从控制器加载表格内容。

结果是,您将获得一个完全 AJAX 化的表格,其中 jQuery DataTables 已自动添加了分页、按表头排序和按关键字过滤功能,而不是一个空表格。表格的示例显示在下图。

Parent-Child-DataTables/jquery-datatables.png

如您所见,jQuery DataTables 插件采用了一个没有内容的普通表格,通过 AJAX 调用填充了行,并添加了排序、过滤和分页的元素。在接下来的部分中,您将看到只需几行 JavaScript 代码即可初始化此表格,并将其转换为功能齐全的 AJAX ized 表格。

您可以在 ** jQuery DataTables 和 ASP.NET MVC 集成 - 第一部分** 文章中找到关于将 jQuery DataTables 插件与 ASP.NET MVC 控制器集成的详细说明。

一旦您实现了控制器并初始化了 jQuery DataTables 插件,它将处理与用户的完整交互。每次用户更改表格的状态时(例如,使用分页更改页面,按列对行排序,或执行搜索),DataTables 插件都会将信息发送到控制器并刷新表格的内容。

然而,在某些情况下,您需要手动刷新表格内容。刷新表格内容是许多应用程序中的常见需求——一些示例如下:

  1. 您可能想添加一个 **刷新** 按钮,允许用户刷新表格中显示的数据。
  2. 您可能想实现表格内容的某种周期性刷新,以便为用户提供最新的数据(例如,某些实时比分实现)。
  3. 您可能想实现某种 AJAX 化的搜索,用户在表单中输入搜索条件,您想在不刷新整个页面的情况下刷新表格中的数据。
  4. 您可能想添加一个主表格或下拉列表,当用户在表格或下拉列表中选择某个值时,您可能想刷新依赖的表格。
  5. 您可能想为表格添加某种过滤器,用户将在其中输入一些文本或在下拉列表中选择某个值,因此您需要刷新表格内容以匹配过滤器。

要实现这些场景,您需要刷新 DataTables 内容。本文的目标是展示如何使用 jQuery DataTables 插件提供的 API 来做到这一点。

这是系列文章的第三篇,解释了 jQuery DataTables 插件如何在 ASP.NET MVC Web 应用程序中集成。如果您不熟悉 DataTables 插件与 ASP.NET MVC 服务器端代码的集成,您可能想在继续之前阅读本系列中的第一篇文章

使用代码

为了说明起见,我们将使用一个简单的 ASP.NET MVC Web 应用程序来列出员工。您需要做的第一件事是创建一个标准的 ASP.NET 模型-视图-控制器结构。此设置需要三个步骤:

  1. 创建代表要显示的数据结构的 Model 类。
  2. 创建将响应用户事件的 Controller 类。
  3. 创建将渲染数据并创建发送到浏览器窗口的 HTML 代码的 View。

此外,您还需要在项目中包含一些 JavaScript 组件。需要下载以下 JavaScript 组件:

  1. jQuery 库 v1.4.4,包含 DataTables 插件使用的标准类。
  2. jQuery DataTables 插件 v1.7.5,包括用于在页面上应用默认样式的可选 DataTables CSS 样式表。

这些文件应存储在本地文件系统中,并包含在客户端渲染的 HTML 页面中。下面将解释这些文件的用法示例。

模型

示例中需要添加两个包含公司和员工信息的类。这些类显示在以下列表中:

public class Company
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string Town { get; set; }
}  
public class Employee
{
    public int EmployeeID { get; set; }
    public string Name { get; set; }
    public string Position { get; set; }
    public int CompanyID { get; set; }
}

员工通过 CompanyID 属性与公司相关联。这些类将用于在页面上显示信息。

视图

View 用于在服务器端渲染数据并将 HTML 代码发送到浏览器。有一个布局页面,用于包含页面上使用的所有必需的 CSS 和 JavaScript 文件。该布局页面如下所示:

<!DOCTYPE html>
<html>
    <head>
        <title>Refreshing table content using a JQuery DataTables plugin</title>
        <link href="@Url.Content("~/Content/dataTables/demo_page.css")" 
         rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/dataTables/demo_table.css")" 
         rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/dataTables/demo_table_jui.css")" 
         rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/themes/base/jquery-ui.css")" 
         rel="stylesheet" type="text/css" media="all" />
        <link href="@Url.Content("~/Content/themes/smoothness/jquery-ui-1.7.2.custom.css")"
         rel="stylesheet" type="text/css" media="all" />
        <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" 
         type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery.dataTables.min.js")" 
         type="text/javascript"></script>
        @RenderSection("head", required: false)
    </head>
    <body id="dt_example">
        <div id="container">
            @RenderBody()
        </div>
    </body>
</html>

布局页面有两个可以填充的区域:

  1. head 区域,页面的 JavaScript 调用将在此处注入。
  2. body 区域,允许使用此布局页面的页面向要在页面上显示的页面注入代码。

在接下来的部分中,我将展示几个使用此布局页面并刷新表格内容的页面实现。

案例 1 - 添加“刷新”按钮

在第一个示例中,我将展示如何添加一个 **刷新** 按钮,当用户按下该按钮时,它将重新加载表格的内容。下图显示了一个示例:

Parent-Child-DataTables/datatable-refresh.png

如上所述,我们需要一个包含表格数据的空表格和一个刷新按钮。页面的 body 显示在以下列表中:

<button id="Refresh" type="button">Refresh<button/>
    <table id="employees" class="display">
        <thead>
            <tr>
                <th>ID</th>
                <th>Employee</th>
                <th>Position</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>

准备好静态 HTML 后,我们需要初始化 DataTables 插件,并为刷新按钮附加一个点击处理程序,该处理程序将重绘表格。代码示例显示在以下列表中。

@section head{
    <script language="javascript" type="text/javascript">
    $(document).ready(function () {

        var oEmployeesTable = $('#employees').dataTable({
            "bJQueryUI": true,
            "bServerSide": true,
            "sAjaxSource": "MasterDetailsAjaxHandler"
        });

        $("#Refresh").click(function (e) {
            oEmployeesTable.fnDraw();
        });
    });
</script>
}

这段代码应该放在视图的 head 部分。文档就绪函数中的第一条语句将 DataTables 插件应用于 employees 表格,指定它将以服务器端模式工作(这意味着在每次用户操作时,插件都会要求服务器端页面提供应显示的新数据),定义通过 AJAX 调用调用的 URL 是 MasterDetailsAjaxHandler - 这是提供表格内容的控制器路径。bJQueryUI 标志不是强制性的——它仅用于将 jQuery UI 样式应用于表格。

当表格初始化时,代码中会添加一个刷新按钮的点击处理程序,该处理程序将绘制表格的内容。每次调用 draw 时,DataTables 插件将再次调用服务器端页面,并获取将加载到表格 body 中的新数据集。

提供内容的控制器在控制器部分进行了描述。

案例 2 - 定期刷新表格内容

如果您不想强制用户刷新表格,可以添加一个函数,该函数将定期调用以刷新表格。代码与案例 1 中显示的代码非常相似。唯一的区别是不需要刷新按钮,并且使用了一个 set interval 函数而不是 click handler,如下面的列表所示:

@section head{
<script language="javascript" type="text/javascript">

    var oEmployeesTable = null;
    function refresh() {
        if (oEmployeesTable != null)
            oEmployeesTable.fnDraw();
    }
    setInterval("refresh()", 1000);

    $(document).ready(function () {
        oEmployeesTable = $('#employees').dataTable({
            "bJQueryUI": true,
            "bServerSide": true,
            "sAjaxSource": "/Home/MasterDetailsAjaxHandler"
        });
    });
</script>
}

在全局作用域中定义了对 employees 表格、刷新表格的函数以及每秒调用刷新函数的计时器的引用。然后在文档就绪处理程序中,使用 DataTables 插件初始化 employees 表格,并设置全局引用。

结果是,此表格将每秒自动重新加载一次。发送到服务器的 AJAX 调用的跟踪显示在下图中:

Parent-Child-DataTables/datatbles-autoreload.png

请注意,对 employees 表格、函数和 interval 调用的引用被放置在全局作用域中,而不是放在文档就绪处理程序的 body 中,因为这些函数引用将在文档就绪处理程序完成时丢失。

案例 3 - 选择父行时刷新表格内容

在此示例中,我将展示当在主表中选择一个公司时,如何刷新从表(employees)的内容。在这种情况下,我们将有两个表格——一个包含公司列表的父表格和一个包含员工列表的子表格。下图显示了那种页面的示例:

Parent-Child-DataTables/ParentChildDataTables.png

当用户在主表中选择公司时,子表中将显示属于该公司的员工。页面的 body 显示在以下列表中:

<div id="demo">
    <table id="companies" class="display">
        <thead>
            <tr>
                <th>Company name</th>
                <th>Address</th>
                <th>Town</th>
            </tr>
        </thead>
        <tbody>
            <tr id="0" class="masterlink">
                <td>Emkay Entertainments</td>
                <td>Nobel House, Regent Centre</td>
                <td>Lothian</td>
            </tr>
            <tr id="1" class="masterlink">
                <td>The Empire</td>
                <td>Milton Keynes Leisure Plaza</td>
                <td>Buckinghamshire</td>
            </tr>
            <tr id="2" class="masterlink">
                <td>Asadul Ltd</td>
                <td>Hophouse</td>
                <td>Essex</td>
            </tr>
            <tr id="3" class="masterlink">
                <td>Ashley Mark Publishing Company</td>
                <td>1-2 Vance Court</td>
                <td>Tyne & Wear</td>
            </tr>
            <tr id="4" class="masterlink">
                <td>MuchMoreMusic Studios</td>
                <td>Unit 29</td>
                <td>London</td>
            </tr>
            <tr id="5" class="masterlink">
                <td>Audio Records Studios</td>
                <td>Oxford Street</td>
                <td>London</td>
            </tr>
        </tbody>
    </table>

    <table id="employees" class="display">
        <thead>
            <tr>
                <th>ID</th>
                <th>Employee</th>
                <th>Position</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
</div> 

包含公司的第一个表格包含五个公司的列表,而 employees 表格是空的。employees 表格将通过 AJAX JavaScript 调用填充。companies 表格中的每一行都包含公司的 ID——此信息将用于加载所选公司的 employees

head 部分包含初始化并连接这两个表格的 JavaScript 代码。JavaScript 初始化代码显示在以下列表中:

<script language="javascript" type="text/javascript">
    $(document).ready(function () {

        /* Initialize master table - optionally */
        var oCompaniesTable = $('#companies').dataTable({ "bJQueryUI": true });
        /* Highlight selected row - optionally */
        $("#companies tbody").click(function (event) {
            $(oCompaniesTable.fnSettings().aoData).each(function () {
                $(this.nTr).removeClass('row_selected');
            });
            $(event.target.parentNode).addClass('row_selected');
        });

        var MasterRecordID = null;

        var oEmployeesTable = $('#employees').dataTable({
            "sScrollY": "100px",
            "bJQueryUI": true,
            "bServerSide": true,
            "sAjaxSource": "MasterDetailsAjaxHandler",
            "bProcessing": true,
            "fnServerData": function (sSource, aoData, fnCallback) {
                aoData.push({ "name": "CompanyID", "value": MasterRecordID });
                $.getJSON(sSource, aoData, function (json) {
                    fnCallback(json)
                });
            }
        });

        $(".masterlink").click(function (e) {
            MasterRecordID = $(this).attr("id");
            oEmployeesTable.fnDraw();
        });
    });
</script>

前两个语句是可选的。第一个语句使用 jQuery DataTables 插件初始化公司表格,以便添加分页、过滤和排序功能(这对于表格之间的父子关系不是必需的,因为父表格可以是一个普通表格)。第二个语句在选定的父表格行上添加 row_selected 类。这也不是必需的,但它有助于突出显示其 employees 显示在子表格中的公司。

本地变量 MasterRecordID 用于保存当前选定公司的 ID。第四条语句初始化子 employees 表格。大多数设置是可选的,并且不影响父子配置,因为初始化中唯一相关的语句是:

  1. 使用 bServerSidesAjaxSource 参数实现的服务器端处理配置。
  2. fnServerData 方法用于将选定公司的 ID 注入到发送到服务器端的 AJAX 调用中。此方法用于将一个名为 CompanyID 的附加参数以及 MasterRecordID 变量的值添加到发送到服务器端的 AJAX 调用中。

最后一条语句附加了事件处理程序,该处理程序填充选定行的 ID,并在每次单击父表格中的行时强制重绘子表格。重绘表格会向服务器端发送 AJAX 请求,并使用属于所选 companyemployee 记录更新表格。

案例 4 - 表单提交时刷新表格

当您需要重新加载表格时,一个常见的场景是您通过 AJAX 提交一些表单内容,并且您想重新加载表格以刷新行。例如,您可能在页面上添加一个添加表单,当成功添加新项目时,您可能想重新加载表格内容。下图显示了那种页面的示例。

Parent-Child-DataTables/datatable-ajax.png

为了创建这种功能,我们需要在视图中添加一个按钮和一个对话框。视图 body 看起来像以下 HTML 代码:

<div id="dialog" title="Add new item">
   <label for="name">Title</label>
   <input type="text" id="name" name="name" value="" />
   <button type="button" id="save">Save</button>
</div>
<button id="add">Add</button>

<table id="employees" class="display">
    <thead>
        <tr>
            <th>ID</th>
            <th>Employee</th>
            <th>Position</th>
        </tr>
    </thead>
    <tbody>
    </tbody>
</table>

HTML 中添加了一个对话框,其中包含用于新项目的文本输入和一个 **保存** 按钮。此外,一个用于打开对话框的按钮被添加到表格上方。已使用 DataTables 插件增强的表格与前面的案例相同。

现在,我们需要在 **保存** 按钮向服务器端提交请求后刷新表格。在这种情况下,我们需要在 AJAX 调用的 success handler 中调用 fnDraw 函数。这种 JavaScript 代码的示例显示在以下列表中:

var oEmployeesTable = $('#employees').dataTable({
    "bJQueryUI": true,
    "bServerSide": true,
    "sAjaxSource": "/Home/MasterDetailsAjaxHandler"
});

$("#dialog").dialog({ autoOpen: false });
$("#add").click(function (e) {
                $("#dialog").dialog("open");
            });

$("#save").click(function (e) {
    e.preventDefault();
    e.stopPropagation();
    $.ajax({
        url: "/Home/AddItem",
        data: {
            name: function(){$("#name").val();}
        },
        success: function () {
            $("#dialog").dialog("close");
            oEmployeesTable.fnDraw();
        }
    });
});

第一部分是标准的 DataTable 初始化,与前面的示例相同。然后初始化对话框(它不会自动打开),在 **添加** 按钮上添加一个打开对话框的处理程序,并在 **保存** 按钮上添加一个提交 AJAX 请求到服务器端页面并发送输入的名称的处理程序。在 AJAX 调用的 success handler 中,关闭对话框并重绘表格。

结果是,每次提交表单时,您都会看到表格被重新加载。

案例 5 - 使用表单元素进行过滤

其他用例的实现与上述三种方法类似。您可以轻松添加一些下拉选择框、复选框,甚至是整个表单来刷新表格内容。

您需要做的就是附加一个事件处理程序,该处理程序将调用 fnDraw 函数,并将您想要通过 AJAX 调用发送到控制器的参数注入到初始化中的 fnServerData 设置中。当调用 fnDraw 时,DataTables 插件将发送一个新的 AJAX 请求,传递 fnServerData 中定义的参数,接受结果,并将它们放入表格。因此,我不会展示其他用例的实现,因为它们非常相似。

如果您想使用直接与表格列相关的表单元素进行刷新,有一个更简单的选项。您可以使用 jQuery DataTables ColumnFilter 附加组件,它可以为 DataTable 添加表单过滤器。如果您在列中或在单独的表单中添加过滤器,您可以看到这个表单过滤器是如何工作的。此过滤器可以应用于表格中已有的行数据,也可以应用于 AJAX 化的表格。使用此插件,您无需实现事件处理程序和 AJAX 请求。您需要做的就是将列过滤器插件应用于服务器端模式配置的 DataTables 插件。以下列表显示了初始化 columnfilter 插件与 DataTables 在服务器端处理模式下的代码示例:

$('#employees').dataTable({
    "bJQueryUI": true,
    "bServerSide": true,
    "sAjaxSource": "MasterDetailsAjaxHandler"
}).columnFilter({
    aoColumns: [ { type: "select"},
             { type: "text" },
             { type: "text" },
             { type: "text" }
        ]
});

此示例为过滤第一列添加了一个下拉列表,为过滤其他列添加了文本框。如果 DataTables 插件以服务器端模式初始化,过滤器也将通过 AJAX 调用发送到服务器端。您可以在 jQuery DataTables ColumnFilter 站点 上找到有关列过滤器配置的更多详细信息。

示例的最后一个必需部分是处理请求的控制器。

Controller

Controller 处理从浏览器发送的请求,并提供将在浏览器中显示的视图/数据。此处,Controller 有两个处理请求的方法:

  1. 当页面加载时返回视图页面的 Load 方法。
  2. Employees AJAX handler,当 jQuery DataTables 发送 AJAX 请求时返回员工。此操作将返回 employees 数据,当 jQuery DataTables 插件想要刷新内容时,因此它应该接受定义表格当前视图状态的标准参数(当前页、每页项数等)。但是,为了支持刷新所选公司的表格(上面的案例 3),在此控制器操作中添加了 company ID 参数,该参数将用于根据公司进一步过滤员工。

第一个 Controller 方法非常简单。此方法仅返回将在浏览器中显示的视图,如以下列表所示:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

第二个 Controller 方法至关重要——它返回 employees 表格的 employees。此方法显示在以下列表中:

public class HomeController : Controller
{
    public ActionResult MasterDetailsAjaxHandler(
             JQueryDataTableParamModel param, int? CompanyID)
    {

        var employees = DataRepository.GetEmployees();

        //"Business logic" method that filters employees by the employer id
        var companyEmployees = (from e in employees
                                where (CompanyID == null || e.CompanyID == CompanyID)
                                select e).ToList();

        //UI processing logic that filter company employees by name and paginates them
        var filteredEmployees = (from e in companyEmployees
                                 where (param.sSearch == null || 
                                 e.Name.ToLower().Contains(param.sSearch.ToLower()))
                                 select e).ToList();
        var result = from emp in filteredEmployees.Skip(
                     param.iDisplayStart).Take(param.iDisplayLength)
                     select new[] { Convert.ToString(emp.EmployeeID), 
                     emp.Name, emp.Position };

        return Json(new
        {
            sEcho = param.sEcho,
            iTotalRecords = companyEmployees.Count,
            iTotalDisplayRecords = filteredEmployees.Count,
            aaData = result
        },
        JsonRequestBehavior.AllowGet);
    }
}

方法的名称必须与 employees 数据表格中设置的 sAjaxSource 参数匹配。此方法接受一个封装 DataTables 插件发送的参数的对象(当前页、排序方向、要显示的项数等)。有关服务器端处理参数的更多详细信息,请参见本系列中的第一篇文章。除了此参数之外,还在方法签名中添加了一个名为 CompanyID 的附加参数。此参数仅与案例三相关,用于按选定的公司 ID 过滤员工。此参数的名称必须与案例 3 中 fnServerData 函数中添加的参数名称匹配。方法中的其他代码只是过滤 employee 数据并以 JSON 格式返回,这是 jQuery DataTables 插件所期望的。有关服务器端配置的更多详细信息,请参见本系列中的第一篇文章

总结

本文展示了如何使用 jQuery DataTables 插件在 ASP.NET MVC 中轻松重新加载表格内容。客户端代码很少,服务器端只需标准的处理函数。此插件允许您以最少的精力和简单的实现指南创建有效的、AJAX 化的 Web 2.0 界面。您可以在此处下载以 ASP.NET MVC 实现的示例项目。

您可能还对本系列中其他文章感兴趣,这些文章展示了:

  1. 如何在 ASP.NET MVC 中使用 jQuery DataTables 插件实现服务器端处理
  2. 如何使用 jQuery DataTables 和几个实现完整数据管理功能的 jQuery 插件在 ASP.NET MVC 中实现完全可编辑的表格

我希望这些文章能在您实现 ASP.NET MVC 应用程序时有所帮助。

历史

  • 2011 年 4 月 5 日:初始版本
© . All rights reserved.