GridView 按需数据填充、自定义分页、客户端排序和其他通用功能





5.00/5 (5投票s)
一篇介绍 GridView 通用功能的文章。
引言
本文将介绍 GridView 控件日常任务的实现。开发人员几乎每天都会遇到这些需求。目标是将所有这些常规任务汇集到一个地方。阅读完本文后,您将了解如何
- 按需填充数据。
- 添加具有多列的记录(比 GridView 显示的列多)
- 在同一页面上编辑 GridView 数据并进行验证。
- 自定义分页。
- 客户端排序。
- 搜索。
- 全选/取消全选记录(客户端)
- 在 GridView 的 itemtemplate 字段中根据条件显示图像。
背景
说实话,我几个月前就开始考虑写这篇文章了。如果您访问本网站的快速答案部分,您会注意到有关 GridView 控件的问题很多。在我看来,GridView 是表示表格数据时最常用的控件,开发人员毫不犹豫地尽可能多地使用它。显然,我们作为开发人员需要定期实现排序、搜索记录、自定义分页、添加、删除、更新等功能。有时用户最初只想在 GridView 中显示几列,但在单击某一行或某一列时,希望显示全部/剩余的详细信息。
大多数情况下,开发人员会采取两种方法(我遇到过并讨论过)。
- 在父 GridView 中添加一个子 GridView 作为 itemtemplate,并使用 rowdatabound 事件来填充它。
- 打开一个弹出窗口,根据通过 querystring 传递的行 ID 显示详细信息。
第一种方法的缺点是成本很高。每次用数据库中的数据填充一行时,都会进行另一个调用来填充子 GridView。这会增加开销,并严重影响应用程序的性能。
第二种方法看起来不太好,尽管它有效,但总会有弹出窗口拦截器可能会搞砸一切。而且 如果客户端系统的安全设置根据其便利性进行了调整,则根本看不到打开的弹出窗口。
那么,解决方案是什么?jQuery。我们将使用 jQuery 的 $.ajax() 方法以 JSON 格式获取详细信息,并将内容填充到模态弹出窗口中。
使用代码
首先,创建一个数据库并在源代码中的 script.txt 文件中运行脚本。修改您的连接字符串,我们就可以开始了。
显示用户详细信息
我们要创建的第一个是 HTTPHandler。此处理程序将以 JSON 格式为我们提供选定用户的详细信息。这也可以通过网页完成,但 HTTPHandlers 对于此类需求总是很好的,因为它们速度很快。它们不必经历页面生命周期。因此,在此 HTTPHandler 中,我们将添加一个类和属性。
public class User
{
public string EDCode { get; set; }
public string EDFirstName { get; set; }
public string EDLastName { get; set; }
public string EDDOB { get; set; }
public string EDCellPhoneNumber { get; set; }
public string EDLandlineNumber { get; set; }
public string EDEmailID { get; set; }
public string EDAddress { get; set; }
public string EDImagePath { get; set; }
public string EDExperience { get; set; }
public string EDSkills { get; set; }
public string EDDesignation { get; set; }
public string EDPreviousCompany { get; set; }
public string EDDOJ { get; set; }
public string EDIsPermanent { get; set; }
public string EDIsReportingManager { get; set; }
public string EDDOB_MMDDYYYY { get; set; }
public string EDDOJ_MMDDYYYY { get; set; }
}
现在是时候填充数据了。为此,函数编写如下
private User GetUserDetails(int Id)
{
var user = new User();
using (SqlConnection con = new SqlConnection(
System.Web.Configuration.WebConfigurationManager.ConnectionStrings[
"SqlConnection"].ConnectionString))
{
con.Open();
DataTable dtFiles = new DataTable();
SqlCommand com = new SqlCommand("SP_GetCompleteUserDetails", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("@userid", Id);
SqlDataReader dr = com.ExecuteReader();
if (dr.HasRows)
{
dr.Read();
user.EDCode = dr["ED_Code"].ToString().Trim();
user.EDFirstName = dr["ED_FirstName"].ToString().Trim();
user.EDLastName = dr["ED_LastName"].ToString().Trim();
user.EDDOB = dr["ED_DOB"].ToString().Trim();
user.EDDOB_MMDDYYYY = Convert.ToDateTime(dr["ED_DOB"]).ToString("MM/dd/yyyy");
user.EDCellPhoneNumber = dr["ED_CellPhoneNumber"].ToString().Trim();
user.EDLandlineNumber = dr["ED_LandlineNumber"].ToString().Trim();
user.EDEmailID = dr["ED_EmailID"].ToString().Trim();
user.EDAddress = dr["ED_Address"].ToString().Trim();
user.EDImagePath = dr["ED_ImagePath"].ToString().Trim();
user.EDExperience = dr["ED_Experience"].ToString().Trim();
user.EDSkills = dr["ED_Skills"].ToString().Trim();
user.EDDesignation = dr["ED_Designation"].ToString().Trim();
user.EDPreviousCompany = dr["ED_PreviousCompany"].ToString().Trim();
user.EDDOJ = dr["ED_DOJ"].ToString().Trim();
user.EDDOJ_MMDDYYYY = Convert.ToDateTime(dr["ED_DOJ"]).ToString("MM/dd/yyyy");
user.EDIsPermanent = dr["ED_IsPermanent"].ToString().Trim();
user.EDIsReportingManager = dr["ED_IsReportingManager"].ToString().Trim();
}
}
return user;
}
现在,当我们拥有 User 类的对象时,我们将将其序列化为 JSON 对象,我们的 HTTPHandler 将返回此对象,我们稍后将使用它来显示所选用户的详细信息。序列化和返回 JSON 对象的代码如下
public void ProcessRequest(HttpContext context)
{
var userDetails = GetUserDetails(Convert.ToInt32(context.Request["EID"].Trim()));
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
string serializedUserDetails = javaScriptSerializer.Serialize(userDetails);
context.Response.ContentType = "text/html";
context.Response.Write(serializedUserDetails);
}
上面的代码是不言自明的。我们所做的就是从数据库中获取详细信息并将其转换为 JSON 对象。现在来看看实际情况:如何在我们的页面上显示这些详细信息。
我在 GridView 的 itemtemplate 中添加了一个标签,并从代码隐藏为其添加了一个属性。标签的标记是:
<asp:Label ID="linkDetails"
runat="server" Text='<%# Eval("ED_Code") %>'
CssClass="userDetails"></asp:Label>
在 GridView 的 rowdatabound 事件中,我们添加了 onclick 属性,如下所示
protected void GridViewUsers_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView rowView = (DataRowView)e.Row.DataItem;
string rowID = rowView["ED_ID"].ToString();
Label linkDetails = new Label();
Button btnEditRow = new Button();
linkDetails = (Label)e.Row.FindControl("linkDetails");
btnEditRow = (Button)e.Row.FindControl("btnEditRow");
linkDetails.Attributes.Add("onclick",
"getDetails('" + rowID + "');");
btnEditRow.Attributes.Add("onclick",
"return getDetailsToEdit('" + rowID + "');");
}
}
在上面的代码中,我为两个控件添加了 onclick 属性。linkDetails 将用于显示所选用户的详细信息,而 btnEditRow 是我用来编辑详细信息的按钮。编辑也将以相同的方式完成(模态弹出窗口)。
互联网上有很多模态弹出窗口。我使用的是 reveal 模态弹出窗口。它轻量级、可配置且非常易于使用。您所要做的就是将模态弹出窗口的内容包装在一个 div 中,然后调用 JavaScript 方法在 pageLoad 或元素单击时显示模态弹出窗口。您可以从 http://zurb.com/playground/reveal-modal-plugin 下载它
获取详细信息的函数如下编写:
function getDetails(objID) {
$.ajax({
url: "AjaxRequestHandler.ashx",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { 'EID': objID },
responseType: "json",
success: OnComplete,
error: OnFail
});
}
成功收到 JSON 对象后,将调用 OnComplete 函数,它将填充 div 内容。OnComplete 函数的实现如下
function OnComplete(result) {
$('#UserDetails').reveal({
animation: 'fadeAndPop',
animationspeed: 300,
closeonbackgroundclick: false,
dismissmodalclass: 'close-reveal-modal'
});
$('#userid').text(result.EDCode);
$('#username').text(result.EDFirstName + ' ' + result.EDLastName);
$('#userdob').text(result.EDDOB);
$('#usercellnumber').text(result.EDCellPhoneNumber);
$('#userlandlinenumber').text(result.EDLandlineNumber);
$('#useremailid').text(result.EDEmailID);
$('#useraddress').text(result.EDAddress);
$('#userexperience').text(result.EDExperience);
$('#userskills').text(result.EDSkills);
$('#userdesignation').text(result.EDDesignation);
$('#userpreviouscompany').text(result.EDPreviousCompany);
$('#userdoj').text(result.EDDOJ);
$('#userpermanent').text(result.EDIsPermanent);
$('#userreportingmanager').text(result.EDIsReportingManager);
$("#userImage").attr("src", 'UserImages/' + result.EDImagePath);
}
现在,当您运行此程序并单击 Employee ID 时,您将得到以下格式的结果
同样,编辑/添加也完成了。记录的添加/更新也使用相同的模态弹出窗口完成。结果将如下所示
实现客户端的选中/取消选中功能
对于选中/取消选中功能,我使用了 jQuery。原因是在 GridView 中查找复选框并用一行代码为所有复选框应用属性非常容易,而不是使用 databound 事件为每个复选框应用属性。代码相当简单。
var selectAllCheckBox = '#<%=GridViewUsers.ClientID%> input[id*="chkAllEmployee"]:checkbox';
var selectEmployeeCheckBox = '#<%=GridViewUsers.ClientID%> input[id*="CheckBoxEmployeeID"]:checkbox';
function CheckUncheckAll() {
var totalCheckboxes = $(selectEmployeeCheckBox);
var checkedCheckboxes = totalCheckboxes.filter(":checked");
var allCheckboxesAreChecked = (totalCheckboxes.length === checkedCheckboxes.length);
$(selectAllCheckBox).attr('checked', allCheckboxesAreChecked);
}
function pageLoad() {
$(selectAllCheckBox).live('click', function () {
$(selectEmployeeCheckBox).attr('checked', $(this).is(':checked'));
CheckUncheckAll();
});
$(selectEmployeeCheckBox).live('click', CheckUncheckAll);
CheckUncheckAll();
上面代码的第一行用于查找 GridView 页眉中的复选框,第二行用于查找所有 ID 为“CheckBoxEmployeeID”的复选框(这些是每一行的复选框)。
接下来有一个函数“CheckUncheckAll”。此函数查找所有复选框,并根据页眉复选框的属性,将 GridView 行中复选框的属性设置为页眉复选框的选中状态。此函数在 pageLoad 方法中调用,以便我们在部分回发时不会丢失绑定。
实现客户端排序
客户端排序是使用 jQuery TableSorter 插件实现的。它可以在 http://tablesorter.com/docs/ 找到。
使用此插件时,唯一重要的是它适用于带有 <THEAD> 和 <TBODY> 标签的 HTML 表,而 GridView 默认不会用这些标签呈现。我们将编写一些代码来生成这些标签。 为此,在将数据绑定到 GridView 后,添加以下代码
if (GridViewUsers.Rows.Count > 0)
{
GridViewUsers.UseAccessibleHeader = true;
GridViewUsers.HeaderRow.TableSection = TableRowSection.TableHeader;
GridViewUsers.FooterRow.TableSection = TableRowSection.TableFooter;
}
实现自定义分页
作为开发人员,我们应始终考虑应用程序的性能。使用 GridView 时,一种常见做法是使用 GridView 自带的默认分页功能。假设您的查询返回 10000 条记录,而 GridView 的页面大小为 50,在初始页面上您将看到 50 条记录,其余 9950 条记录将被截断。这不是个好主意。您可以编写查询,使其仅返回所需的行。幸运的是,SQL Server 中有一个 rowcount 属性可以派上用场。我们将传递页索引和要获取的记录数,存储过程将只返回 这些行。存储过程的脚本可以在源代码中找到,SQL 代码非常简单易懂。
关注点
我已尽力使代码尽可能简单。示例代码仍有改进的空间。欢迎提出建议和批评。希望您会发现本文很有帮助。有关源代码的任何解释和疑问,请随时评论。