Jul*_*n N 66 asp.net sorting gridview
我有一个gridview,我需要在用户点击标题时对其元素进行排序.
它的数据源是一个List对象.
aspx以这种方式定义:
<asp:GridView ID="grdHeader" AllowSorting="true" AllowPaging="false"
AutoGenerateColumns="false" Width="780" runat="server" OnSorting="grdHeader_OnSorting" EnableViewState="true">
<Columns>
<asp:BoundField DataField="Entitycode" HeaderText="Entity" SortExpression="Entitycode" />
<asp:BoundField DataField="Statusname" HeaderText="Status" SortExpression="Statusname" />
<asp:BoundField DataField="Username" HeaderText="User" SortExpression="Username" />
</Columns>
</asp:GridView>
Run Code Online (Sandbox Code Playgroud)
后面的代码是这样定义的:
首先加载:
protected void btnSearch_Click(object sender, EventArgs e)
{
List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
this.grdHeader.DataSource = items;
this.grdHeader.DataBind();
}
Run Code Online (Sandbox Code Playgroud)
当用户点击标题时:
protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e)
{
List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
items.Sort(new Helpers.GenericComparer<V_ReportPeriodStatusEntity>(e.SortExpression, e.SortDirection));
grdHeader.DataSource = items;
grdHeader.DataBind();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是e.SortDirection始终设置为Ascending.
我有一个类似代码的网页,它运作良好,e.SortDirection在升序和降序之间交替.
我做错了什么 ?
小智 51
Session和Viewstate的问题在于,如果页面上有多个gridview,您还必须跟踪存储SortColumn和Direction的gridview控件.
Session和Viewstate的替代方法是向Gridview添加2个属性,并以这种方式跟踪Column和Direction.
这是一个例子:
private void GridViewSortDirection(GridView g, GridViewSortEventArgs e, out SortDirection d, out string f)
{
f = e.SortExpression;
d = e.SortDirection;
//Check if GridView control has required Attributes
if (g.Attributes["CurrentSortField"] != null && g.Attributes["CurrentSortDir"] != null)
{
if (f == g.Attributes["CurrentSortField"])
{
d = SortDirection.Descending;
if (g.Attributes["CurrentSortDir"] == "ASC")
{
d = SortDirection.Ascending;
}
}
g.Attributes["CurrentSortField"] = f;
g.Attributes["CurrentSortDir"] = (d == SortDirection.Ascending ? "DESC" : "ASC");
}
}
Run Code Online (Sandbox Code Playgroud)
小智 33
您可以使用会话变量来存储最新的排序表达式,并在下次对网格进行排序时将网格的排序表达式与存储最后一个排序表达式的Session变量进行比较.如果列相等,则检查先前排序的方向并按相反方向排序.
例:
DataTable sourceTable = GridAttendence.DataSource as DataTable;
DataView view = new DataView(sourceTable);
string[] sortData = ViewState["sortExpression"].ToString().Trim().Split(' ');
if (e.SortExpression == sortData[0])
{
if (sortData[1] == "ASC")
{
view.Sort = e.SortExpression + " " + "DESC";
this.ViewState["sortExpression"] = e.SortExpression + " " + "DESC";
}
else
{
view.Sort = e.SortExpression + " " + "ASC";
this.ViewState["sortExpression"] = e.SortExpression + " " + "ASC";
}
}
else
{
view.Sort = e.SortExpression + " " + "ASC";
this.ViewState["sortExpression"] = e.SortExpression + " " + "ASC";
}
Run Code Online (Sandbox Code Playgroud)
max*_*oin 20
简单的解决方案:
protected SortDirection GetSortDirection(string column)
{
SortDirection nextDir = SortDirection.Ascending; // Default next sort expression behaviour.
if (ViewState["sort"] != null && ViewState["sort"].ToString() == column)
{ // Exists... DESC.
nextDir = SortDirection.Descending;
ViewState["sort"] = null;
}
else
{ // Doesn't exists, set ViewState.
ViewState["sort"] = column;
}
return nextDir;
}
Run Code Online (Sandbox Code Playgroud)
非常类似于ViewState上的默认GridView排序和轻量级.
用法:
protected void grdHeader_OnSorting(object sender, GridViewSortEventArgs e)
{
List<V_ReportPeriodStatusEntity> items = GetPeriodStatusesForScreenSelection();
items.Sort(new Helpers.GenericComparer<V_ReportPeriodStatusEntity>(e.SortExpression, GetSortDirection(e.SortExpression));
grdHeader.DataSource = items;
grdHeader.DataBind();
}
Run Code Online (Sandbox Code Playgroud)
San*_*der 19
自动双向排序仅适用于SQL数据源.不幸的是,MSDN中的所有文档都假设您正在使用它,因此GridView可能会有点令人沮丧.
我这样做的方法是自己跟踪订单.例如:
protected void OnSortingResults(object sender, GridViewSortEventArgs e)
{
// If we're toggling sort on the same column, we simply toggle the direction. Otherwise, ASC it is.
// e.SortDirection is useless and unreliable (only works with SQL data source).
if (_sortBy == e.SortExpression)
_sortDirection = _sortDirection == SortDirection.Descending ? SortDirection.Ascending : SortDirection.Descending;
else
_sortDirection = SortDirection.Ascending;
_sortBy = e.SortExpression;
BindResults();
}
Run Code Online (Sandbox Code Playgroud)
小智 15
此问题不仅存在于SQL数据源中,也存在于对象数据源中.但是,在代码中动态设置DataSource时,就会发生这种情况.不幸的是,MSDN有时候信息非常糟糕.简单地提一下这种行为(这不是错误,而是设计问题)可以节省大量时间.无论如何,我不太倾向于使用Session变量.我通常将排序方向存储在ViewState中.
rjz*_*zii 10
我这样做的方式类似于接受的答案提供的代码,位有点不同所以我想我也会把它放在那里.请注意,在将DataTable绑定到GridView .DataSource 之前,正在对DataTable进行此排序.
选项一:使用ViewState
void DataGrid_Sorting(object sender, GridViewSortEventArgs e)
{
if (e.SortExpression == (string)ViewState["SortColumn"])
{
// We are resorting the same column, so flip the sort direction
e.SortDirection =
((SortDirection)ViewState["SortColumnDirection"] == SortDirection.Ascending) ?
SortDirection.Descending : SortDirection.Ascending;
}
// Apply the sort
this._data.DefaultView.Sort = e.SortExpression +
(string)((e.SortDirection == SortDirection.Ascending) ? " ASC" : " DESC");
ViewState["SortColumn"] = e.SortExpression;
ViewState["SortColumnDirection"] = e.SortDirection;
}
Run Code Online (Sandbox Code Playgroud)
选项二:使用会话
请注意,如果您在字段中看到以下情况,或者您仍然支持定位到旧版浏览器的公司系统,则会为传统目的提供以下内容.
void DataGrid_Sorting(object sender, GridViewSortEventArgs e)
{
if (e.SortExpression == (string)HttpContext.Current.Session["SortColumn"])
{
// We are resorting the same column, so flip the sort direction
e.SortDirection =
((SortDirection)HttpContext.Current.Session["SortColumnDirection"] == SortDirection.Ascending) ?
SortDirection.Descending : SortDirection.Ascending;
}
// Apply the sort
this._data.DefaultView.Sort = e.SortExpression +
(string)((e.SortDirection == SortDirection.Ascending) ? " ASC" : " DESC");
HttpContext.Current.Session["SortColumn"] = e.SortExpression;
HttpContext.Current.Session["SortColumnDirection"] = e.SortDirection;
}
Run Code Online (Sandbox Code Playgroud)
我不知道为什么每个人都忘记使用隐藏的字段!它们比ViewState(我自2005年以来关闭)"便宜"得多.如果您不想使用Session或ViewState,那么这是我的解决方案:
将这两个隐藏字段放在您的aspx页面上,并为您的数据设置所需的默认排序(例如我使用LastName):
<asp:HiddenField ID="hfSortExpression" runat="server" Value="LastName" />
<asp:HiddenField ID="hfSortDirection" runat="server" Value="Ascending" />
Run Code Online (Sandbox Code Playgroud)
然后把这个帮助代码放在你的Base页面中(你有一个基页不是吗?如果没有,请将你的.cs代码放在后面).
/// <summary>
/// Since native ASP.Net GridViews do not provide accurate SortDirections,
/// we must save a hidden field with previous sort Direction and Expression.
/// Put these two hidden fields on page and call this method in grid sorting event
/// </summary>
/// <param name="hfSortExpression">The hidden field on page that has the PREVIOUS column that is sorted on</param>
/// <param name="hfSortDirection">The hidden field on page that has the PREVIOUS sort direction</param>
protected SortDirection GetSortDirection(GridViewSortEventArgs e, HiddenField hfSortExpression, HiddenField hfSortDirection)
{
//assume Ascending always by default!!
SortDirection sortDirection = SortDirection.Ascending;
//see what previous column (if any) was sorted on
string previousSortExpression = hfSortExpression.Value;
//see what previous sort direction was used
SortDirection previousSortDirection = !string.IsNullOrEmpty(hfSortDirection.Value) ? ((SortDirection)Enum.Parse(typeof(SortDirection), hfSortDirection.Value)) : SortDirection.Ascending;
//check if we are now sorting on same column
if (e.SortExpression == previousSortExpression)
{
//check if previous direction was ascending
if (previousSortDirection == SortDirection.Ascending)
{
//since column name matches but direction doesn't,
sortDirection = SortDirection.Descending;
}
}
// save them back so you know for next time
hfSortExpression.Value = e.SortExpression;
hfSortDirection.Value = sortDirection.ToString();
return sortDirection;
}
Run Code Online (Sandbox Code Playgroud)
接下来,您需要在网格排序事件处理程序中处理排序.在调用获取数据的main方法之前,从排序事件处理程序调用上面的方法
protected void gridContacts_Sorting(object sender, GridViewSortEventArgs e)
{
//get the sort direction (since GridView sortDirection is not implemented!)
SortDirection sortDirection = GetSortDirection(e, hfSortExpression, hfSortDirection);
//get data, sort and rebind (obviously, this is my own method... you must replace with your own)
GetCases(_accountId, e.SortExpression, sortDirection);
}
Run Code Online (Sandbox Code Playgroud)
由于有很多例子使用DataTables或DataViews或其他非LINQ友好集合,我想我会包含一个示例调用中间层方法返回一个通用列表,并使用LINQ进行排序以完善这个例子让它变得更"现实世界":
private void GetCases(AccountID accountId, string sortExpression, SortDirection sortDirection)
{
//get some data from a middle tier method (database etc._)(
List<PendingCase> pendingCases = MyMiddleTier.GetCasesPending(accountId.Value);
//show a count to the users on page (this is just nice to have)
lblCountPendingCases.Text = pendingCases.Count.ToString();
//do the actual sorting of your generic list of custom objects
pendingCases = Sort(sortExpression, sortDirection, pendingCases);
//bind your grid
grid.DataSource = pendingCases;
grid.DataBind();
}
Run Code Online (Sandbox Code Playgroud)
最后,这是在自定义对象的通用列表上使用LINQ进行的向下和脏排序.我确信那里会有更好的东西可以解决问题,但这说明了这个概念:
private static List Sort(string sortExpression,SortDirection sortDirection,List pendingCases){
switch (sortExpression)
{
case "FirstName":
pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.FirstName).ToList() : pendingCases.OrderByDescending(c => c.FirstName).ToList();
break;
case "LastName":
pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.LastName).ToList() : pendingCases.OrderByDescending(c => c.LastName).ToList();
break;
case "Title":
pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.Title).ToList() : pendingCases.OrderByDescending(c => c.Title).ToList();
break;
case "AccountName":
pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.AccountName).ToList() : pendingCases.OrderByDescending(c => c.AccountName).ToList();
break;
case "CreatedByEmail":
pendingCases = sortDirection == SortDirection.Ascending ? pendingCases.OrderBy(c => c.CreatedByEmail).ToList() : pendingCases.OrderByDescending(c => c.CreatedByEmail).ToList();
break;
default:
break;
}
return pendingCases;
}
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要(我已经说过了吗?)你可能想在你的Page_Load处理程序中添加这样的东西,以便网格在页面加载时默认绑定...注意_accountId是一个查询字符串参数,转换为自定义在这种情况下我自己的AccountID类型......
if (!Page.IsPostBack)
{
//sort by LastName ascending by default
GetCases(_accountId,hfSortExpression.Value,SortDirection.Ascending);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
126341 次 |
最近记录: |