ASP.NET 扩展 Grid 控件






3.60/5 (8投票s)
EnhanceGrid:支持自定义分页、每页记录数和搜索功能。
引言
在本文中,我将讨论我的 EnhanceGrid,它具有以下功能:
- 自定义分页,仅提取所需的记录数
- 列标题中的图标,用于显示排序方向
- 分页器中的下拉列表,用于调整每页的记录数
- 扩展 Grid 的属性
- 如何使用自定义 Grid 控件
自定义分页,仅提取所需的记录数
以下是我用于为自定义 Grid 提供自定义分页功能的存储过程。注释解释了字段并提供了有关存储过程的详细信息。
CREATE PROCEDURE [dbo].[GetRequestedRecordByPage]
@FromList nvarchar(200) -- Table Name
,@SortingCol nvarchar(200) -- Sorting column Name
,@SelectList nvarchar(200) = '*' -- Select columns list
,@WhereClause nvarchar(200) = '' -- Where clause i.e condition
,@PageNum int = 1 -- Requested page number
,@PageSize int = 5 -- No of record in page
,@TotalNoOfRecord int output -- Total no of selected records
AS
Begin
SET NOCOUNT ON
DECLARE @Query nvarchar(max) -- query going to be execute
IF rtrim(ltrim(@WhereClause)) <> ''
BEGIN
SET @Query ='SELECT @TotalNoOfRecord = COUNT(*)
FROM ' + @FromList + '
WHERE ' + @WhereClause
END
ELSE
BEGIN
SET @Query ='SELECT @TotalNoOfRecord = COUNT(*)
FROM ' + @FromList
END
/* Count no. of record */
EXEC sp_executeSQL
@Query,
@params = N'@TotalNoOfRecord INT OUTPUT',
= @TotalNoOfRecord OUTPUT
DECLARE @lbound int, @ubound int
/* Calculating upper and lower bound */
SET @lbound = ((@PageNum - 1) * @PageSize)
SET @ubound = @lbound + @PageSize + 1
/* Get list of record(s) */
SELECT @Query = ''
SELECT @Query = 'SELECT *
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY ' + @SortingCol + ') AS rownumber,' +@SelectList +
' FROM ' + @FromList
IF rtrim(ltrim(@WhereClause)) <> ''
BEGIN
SELECT @Query = @Query + ' WHERE ' + @WhereClause
END
SELECT @Query = @Query + ' ) AS tbl
WHERE rownumber > ' + CONVERT(varchar(9), @lbound) +
' AND rownumber < ' + CONVERT(varchar(9), @ubound)
EXEC (@Query)
End
正如您所看到的,上述过程是通用的,因此可以用于任何地方。因此,我已将其包含在我的 EnhanceGrid 中,因为它适用于用 ASP.NET 开发的任何项目。
列标题中的图标,用于显示排序方向
为了在标题文本中显示排序图标,我覆盖了 .NET Framework 中标准 Grid
控件的以下事件。
OnRowCreated
:在创建行时会触发此事件。这里,如果RowType
是Header
,则通过获取被单击项的索引来添加排序图标,然后调用SortingIcon
方法将图标添加到标题行。
protected override void OnRowCreated(GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
/* Get sorting column index */
int index = GetSortColumnIndex();
if (index != -1)
{
sortingIcon(index, e.Row);
}
}
}
OnSorting
:当用户单击标题列以对 Grid 控件的记录进行排序时,将调用此事件。从下面的代码可以看出,它将列排序表达式存储在 lblSortExp
中,将排序方向存储在 lblSortDirection
中,并反转当前存储的值。protected override void OnSorting(GridViewSortEventArgs e)
{
try
{
lblSortExp = e.SortExpression;
switch (lblSortDirection)
{
case "asc":
{
lblSortDirection = "desc";
break;
}
case "desc":
case "":
case null:
{
lblSortDirection = "asc";
break;
}
}
BindGrid();
}
catch (Exception ex) { }
}
sortingIcon
:此函数用于在列标题中添加排序图标。在此函数中,我创建了一个 Label
,该 Label 动态添加到被单击标题列的标题文本中。private void sortingIcon(int index, GridViewRow row)
{
System.Web.UI.WebControls.Label lblSorting =
new System.Web.UI.WebControls.Label();
if (lblSortDirection == "desc")
{
lblSorting.Text = "<span style=\"font-family:" +
"Marlett; font-weight:bold\">6</span>";
}
else
{
lblSorting.Text = "<span style=\"font-family:Marlett;" +
" font-weight:bold\">5</span>";
}
row.Cells[index].Controls.Add(lblSorting);
}
GetSortColumnIndex
:此函数用于获取用户单击以进行排序的列的索引。在此函数中,我将单击的列的排序表达式与每一列进行比较,并获取被单击列的索引。这是必需的,因为我不知道被单击列的索引。private int GetSortColumnIndex()
{
foreach (DataControlField field in this.Columns)
{
if (field.SortExpression.ToString() == lblSortExp)
{
return this.Columns.IndexOf(field);
}
}
return -1;
}
分页器中的下拉列表,用于调整每页的记录数
对于每页记录数,我覆盖了与显示排序图标时相同的函数,但这里的条件已更改。正如您下面看到的,我检查了分页器类型的行。在下面的代码中,我创建了一个下拉列表控件,其中包含每页的记录数以及附加的选定更改事件。
protected override void OnRowCreated(GridViewRowEventArgs e)
{
try
{
if (e.Row.RowType == DataControlRowType.Pager)
{
DropDownList ddl ddlNoPages = new DropDownList();
//adds variants of pager size
ddlNoPages.Items.Add("10");
ddlNoPages.Items.Add("50");
ddlNoPages.Items.Add("100");
ddlNoPages.AutoPostBack = true;
//selects item due to the GridView current page size
ListItem li = ddlNoPages.Items.FindByText(this.PageSize.ToString());
if (li != null)
ddlNoPages.SelectedIndex = ddlNoPages.Items.IndexOf(li);
ddlNoPages.SelectedIndexChanged +=
new EventHandler(ddlNoPages _SelectedIndexChanged);
//adds dropdownlist in the additional cell to the pager table
Table pagerTable = e.Row.Cells[0].Controls[0] as Table;
TableCell cell = new TableCell();
cell.Style["padding-left"] = "50px";
cell.Style["text-align"] = "right";
cell.Controls.Add(new LiteralControl("Page Size:"));
cell.Controls.Add(ddlNoPages);
//e.Row.Cells[0].Controls.Add(cell);
pagerTable.Rows[0].Cells.Add(cell);
}
}
catch (Exception ex)
{
}
}
当组合框索引更改时,将触发以下事件。代码非常简单易懂,因此我认为无需详细解释。
void ddlNoPages_SelectedIndexChanged(object sender, EventArgs e)
{
if (PageSize > int.Parse(((DropDownList)sender).SelectedValue))
IsPagesizeChanged = true;
else
IsPagesizeChanged = false;
PageIndex = 0;
//changes page size
PageSize = int.Parse(((DropDownList)sender).SelectedValue);
//binds data source
BindGrid();
}
注意:此方法仍存在一些我正在处理的错误,我将提供完整的解决方案。
在完成上述操作后,您需要为自定义分页存储过程覆盖 Grid 的以下方法才能正常工作。在此方法中,您必须为分页数据源属性设置值。
protected override void InitializePager(GridViewRow row,
int columnSpan, PagedDataSource pagedDataSource)
{
try
{
#region code for standard paging
//To set custome paging
pagedDataSource.AllowCustomPaging = true;
//To set total no of records retived
pagedDataSource.VirtualCount = Convert.ToInt32(lbltotal);
//To set current page index
pagedDataSource.CurrentPageIndex = lblpageIndex;
#endregion code for standard paging
base.InitializePager(row, columnSpan, pagedDataSource);
}
catch (Exception ex) { }
}
您也可以根据客户要求覆盖上述方法,以提供不同类型的自定义分页。
扩展 Grid 的属性
请注意,大多数属性的值都来自 ViewState,并在 ViewState 中设置。正是通过使用 ViewState 机制,Grid 在回发事件期间才能保留属性值。
这里需要注意的另一件事是,控件 ID 附加到每个 ViewState 属性,因为如果您将相同的 Grid 控件拖放到一个页面上两次或更多次,它将正常工作而不会干扰其他 Grid 操作。
lbltotal
:Grid 的此属性用于存储存储过程检索的总记录数;它用于相应地调整分页。
public int lbltotal
{
get
{
if (null != ViewState["lbltotal" + ControlID])
return (int)ViewState["lbltotal" + ControlID];
else
return 0;
}
set
{
ViewState["lbltotal" + ControlID] = value;
}
}
lblpageIndex
:存储当前页索引。public int lblpageIndex
{
get
{
if (null != ViewState["lblpageIndex" + ControlID])
return (int)ViewState["lblpageIndex" + ControlID];
else
return 0;
}
set
{
ViewState["lblpageIndex" + ControlID] = value;
}
}
lblSortDirection
:存储列的排序方向。public string lblSortDirection
{
get
{
if (null != ViewState["lblSortDirection" + ControlID])
return (string)ViewState["lblSortDirection" + ControlID];
else
return string.Empty;
}
set
{
ViewState["lblSortDirection" + ControlID] = value;
}
}
lblSortExp
:存储排序表达式,即列排序表达式。public string lblSortExp
{
get
{
if (null != ViewState["lblSortExp" + ControlID])
return (string)ViewState["lblSortExp" + ControlID];
else
return string.Empty;
}
set
{
ViewState["lblSortExp" + ControlID] = value;
}
}
FromClause
:存储传递给存储过程以检索记录的查询的 From
子句。public string FromClause
{
get
{
if (null != ViewState["fromClause" + ControlID])
return (string)ViewState["fromClause" + ControlID];
else
return string.Empty;
}
set
{
ViewState["fromClause" + ControlID] = value;
}
}
WhereClause
:存储作为查询的 WHERE 条件传递给存储过程的查询的 Where
子句。public string WhereClause
{
get
{
if (null != ViewState["whereClause" + ControlID])
return (string)ViewState["whereClause" + ControlID];
else
return string.Empty;
}
set
{
ViewState["whereClause" + ControlID] = value;
}
}
SelectList
:存储将传递给存储过程的 SELECT 列表列名。public string SelectList
{
get
{
if (null != ViewState["selectList" + ControlID])
return (string)ViewState["selectList" + ControlID];
else
return string.Empty;
}
set
{
ViewState["selectList" + ControlID] = value;
}
}
ControlID
:存储控件的 ID。private string _controlId;
public string ControlID
{
get { return _controlId; }
set { _controlId = value; }
}
DefaultSortExp
:存储 Grid 在第一次排序事件发生之前用于排序目的的默认排序表达式。private string _DefaultSortExp;
public string DefaultSortExp
{
set{ _DefaultSortExp = value;}
get{ return _DefaultSortExp;}
}
其他重要事项
以下属性允许在使用 Grid 控件时附加您自己的事件。
public event GridViewRowEventHandler onRowCreate
{
add
{
base.RowCreated += value;
}
remove
{
base.RowCreated -= value;
}
}
public event GridViewSortEventHandler onSort
{
add
{
base.Sorting += value;
}
remove
{
base.Sorting -= value;
}
}
如何使用自定义 Grid 控件
以下是注册 Grid 控件的页面代码。
<%@ Register TagPrefix="cc" Namespace="AppEngine.ComponentControls" Assembly="__code" %>
这是在使用 Grid 控件的 ASPX 页面上的代码。
<cc:MyGridView runat="server" ID="grdEmployee"
AutoGenerateColumns="False" AllowPaging="true"
AllowSorting="true" DefaultSortExp="FIRSTNAME"
EnableSortingAndPagingCallbacks = "false">
<Columns>
<asp:BoundField DataField="FIRSTNAME"
HeaderText="FIRSTNAME" SortExpression="FIRSTNAME" />
<asp:BoundField DataField="LASTNAME"
HeaderText="LASTNAME" SortExpression="LASTNAME" />
<asp:BoundField DataField="LOGINNAME"
HeaderText="LOGINNAME" SortExpression="LOGINNAME" />
<asp:BoundField DataField="EMAIL"
HeaderText="EMAIL" SortExpression="EMAIL" />
</Columns>
<PagerSettings Mode="NumericFirstLast" Position ="TopAndBottom"
PageButtonCount="5" />
<PagerStyle BackColor="Pink" />
</cc:MyGridView>
以下代码是您 aspx.cs 文件的一部分。从下面的代码可以看出,我指定了 SelectList
(这是一个列列表);FromClause
包含表名,这里是 Employee;WhereClause
包含筛选条件。
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
grdEmployee.SelectList = "[FIRSTNAME],[LASTNAME],[LOGINNAME],[EMAIL]";
grdEmployee.FromClause = "[EMPLOYEE]";
grdEmployee.WhereClause = string.Empty;
//grdEmployee.WhereClause = "[FIRSTNAME] like '%a'";
grdEmployee.BindGrid();
}
}
Grid 搜索
以下是 EnhanceGrid 控件中搜索数据的示例。
为了搜索,我在放置 Grid 控件的页面上添加了以下控件,这有助于搜索记录。
ddlColumn
:包含将由 EnhanceGrid 控件显示的列名。这里需要注意的是,列表项的值字段是数据库表列的名称。txtValue
:控件允许用户输入要搜索特定列的值。
<div style="width: 100%;">
<div style="float: left; width : 10%;">
<asp:Label runat="server" ID="lblSearch" Text="Select Criteria"></asp:Label>
</div>
<div style="float: left; width :10%;">
<asp:DropDownList runat="server" ID="ddlColumn">
<asp:ListItem Text="First Name" Value="FIRSTNAME"></asp:ListItem>
<asp:ListItem Text="Last Name" Value="LASTNAME"></asp:ListItem>
<asp:ListItem Text="Login ID" Value="LOGINNAME"></asp:ListItem>
<asp:ListItem Text="E-mail ID" Value="EMAIL"></asp:ListItem>
</asp:DropDownList>
</div>
<div style="float: left; width :10%;">
<asp:Label runat="server" ID="lblValue" Text="Value"></asp:Label>
</div>
<div style="float: left; width :15%;">
<asp:TextBox runat="server" ID="txtValue" ></asp:TextBox>
</div>
<div>
<asp:Button runat="server" ID="btnSearch" Text="Search"
onclick="btnSearch_Click" />
</div>
</div>
btnSearch
:包含从数据库搜索特定数据的代码。从下面的代码可以看出,如果 txtValue
文本字段中有值,它会形成一个 Where
子句,如果不存在,则传递一个空的 Where
子句,这将搜索 Grid 控件的所有记录。protected void btnSearch_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtValue.Text))
{
grdEmployee.WhereClause = ddlColumn.SelectedValue +
" like '%" + txtValue.Text + "%'";
}
else
{
grdEmployee.WhereClause = string.Empty;
}
grdEmployee.SelectList =
"[FIRSTNAME],[LASTNAME],[LOGINNAME],[EMAIL]";
grdEmployee.FromClause = "[EMPLOYEE]";
grdEmployee.BindGrid();
}