在ASP.NET中,GridView控件是一个非常强大的工具,用于显示和操作数据。然而,为了实现搜索和分页功能,开发者往往需要编写大量的代码。本文将介绍如何创建一个可重用的控件,以简化这一过程。
背景:在之前的项目中,一直在ASP.NET页面上使用类似的代码来实现搜索/过滤功能。虽然这些代码能够正常工作,但重复编写和对齐文本框等控件非常耗时。因此,决定创建一个可以自动完成所有工作的可重用控件。已经在SQL Server 2008上测试了这个GridView,认为任何人都可以通过更改存储过程的语法和连接,来使用其他数据库。
扩展了System.Web.UI.WebControls.BoundField
类,并添加了一个名为SearchExpression
的属性,用于保存将直接传递给SQL存储过程的搜索表达式。
public class SearchBoundField : System.Web.UI.WebControls.BoundField
{
private const string SEARCH_EXPRESSION = "SearchExpression";
public string SearchExpression
{
get
{
if (this.ViewState[SEARCH_EXPRESSION] == null)
{
this.ViewState[SEARCH_EXPRESSION] = this.DataField;
}
return (string)this.ViewState[SEARCH_EXPRESSION];
}
set
{
this.ViewState[SEARCH_EXPRESSION] = value;
}
}
}
控件将在GridView的每个列顶部创建文本框,并在最后一列创建一些额外的按钮,如“过滤”和“取消过滤”。当调用GridView.DataBound()
时,它将创建带有页脚行的行,该行将包含导航控件框和记录状态标签。
在带有导航控件的页脚行中,可以看到总记录数、当前页码和总页数。这是引用数据源,它将有一个名为TotalRows
的列。
可以通过点击导航按钮来跳转到下一页、上一页、最后一页、第一页,或者通过点击导航按钮跳转到指定页。
以下是一些用于此目的的属性:
public bool ShowEmptyFooter;
public int TotalSearchRecords;
public int TotalSearchPages;
public int? CurrentSearchPageNo;
public bool SelectableDataRow;
ShowEmptyFooter
属性用于在没有记录时隐藏/显示空页脚。TotalSearchRecords
属性将保存当前搜索存在的总记录数。TotalSearchPages
属性保存当前搜索存在的总页数。通常,这将通过使用TotalSearchRecords
和PageSize
来计算。
CurrentSearchPageNo
属性将保存当前页码。当用户浏览页面时,这个值会改变。当用户点击页面更改按钮时,数据将从数据库中获取,并重建网格。
SelectableDataRow
是一个重要的属性,用于指定网格是否能够接受行点击事件。如果是true
,在构建网格时,以下代码将被添加到OnRowDataBound
中:
protected override void OnRowDataBound(GridViewRowEventArgs e)
{
base.OnRowDataBound(e);
if (SelectableDataRow == true)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#ceedfc'");
e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor=''");
e.Row.Attributes.Add("style", "cursor:pointer;");
e.Row.Attributes.Add("onclick", Page.ClientScript.GetPostBackClientHyperlink(this, "Select$" + e.Row.RowIndex));
}
}
}
InitSearchFilterData
方法用于初始化搜索过滤数据。
public DataTable SearchFilters;
上述属性用于存储SearchFilters DataTable
,当每次搜索调用发生时,将创建一个带有SearchString
和Value
的数据表,这将传递给SQL存储过程,存储过程将解析Datatable
并构建动态SQL查询并执行它。
public string CurrentSortExpression;
public string CurrentSortDirection;
上述两个属性用于存储当前排序表达式和排序方向,这些将传递给SQL过程以构建查询。当用户点击列标题时,属性的值将改变。
当用户点击过滤按钮时,将发生FilterButtonClick
事件,需要像以下代码一样在前端处理该事件:
public void sgvSearchClientMaster_FilterButtonClick(object sender, SearchGridEventArgs e)
{
FilterToNthPage(e.SearchFilterValues, sgvSearchClientMaster.CurrentSortExpression, sgvSearchClientMaster.CurrentSortDirection, 1);
}
当用户点击任何一个导航按钮时,将发生NavigationButtonClick
事件,需要像以下代码一样处理它:
public void sgvSearchClientMaster_NavigationButtonClick(object sender, NavigationButtonEventArgs e)
{
if (e.NavigationButtonsType == NavigationButtonsTypes.GoFirst)
{
FilterToNthPage(sgvSearchClientMaster.SearchFilters, sgvSearchClientMaster.CurrentSortExpression, sgvSearchClientMaster.CurrentSortDirection, 1);
}
else if (e.NavigationButtonsType == NavigationButtonsTypes.GoLast)
{
FilterToNthPage(sgvSearchClientMaster.SearchFilters, sgvSearchClientMaster.CurrentSortExpression, sgvSearchClientMaster.CurrentSortDirection, sgvSearchClientMaster.TotalSearchPages);
}
else if (e.NavigationButtonsType == NavigationButtonsTypes.GoNext)
{
if (sgvSearchClientMaster.CurrentSearchPageNo < sgvSearchClientMaster.TotalSearchPages)
{
FilterToNthPage(sgvSearchClientMaster.SearchFilters, sgvSearchClientMaster.CurrentSortExpression, sgvSearchClientMaster.CurrentSortDirection, (int)sgvSearchClientMaster.CurrentSearchPageNo + 1);
}
}
else if (e.NavigationButtonsType == NavigationButtonsTypes.GoPrevious)
{
if (sgvSearchClientMaster.CurrentSearchPageNo > 1)
{
FilterToNthPage(sgvSearchClientMaster.SearchFilters, sgvSearchClientMaster.CurrentSortExpression, sgvSearchClientMaster.CurrentSortDirection, (int)sgvSearchClientMaster.CurrentSearchPageNo - 1);
}
}
else if (e.NavigationButtonsType == NavigationButtonsTypes.GoToPage)
{
FilterToNthPage(sgvSearchClientMaster.SearchFilters, sgvSearchClientMaster.CurrentSortExpression, sgvSearchClientMaster.CurrentSortDirection, (int)e.PageIndex);
}
}
SqlParameter tvpParam = cmd.Parameters.AddWithValue(SQLTableVariableName, SearchFilterValues);
tvpParam.SqlDbType = SqlDbType.Structured;