如何在使用自定义数据源的ASP.NET GridView中对列进行排序?

5

当我使用自定义SqlDataSource时,我的GridView无法启用用户对数据列进行排序。

我有一个GridView,在HTML中对它的引用代码很少:

<asp:GridView id="grid" runat="server" AutoGenerateColumns="False" AllowSorting="True">
</asp:GridView>

在代码后台,我附加了一个动态创建的SqlDataSource(它包含的列并不总是相同的,因此用于创建它的SQL是在运行时构建的)。例如:
我设置了列...
BoundField column = new BoundField();
column.DataField = columnName;
column.HeaderText = "Heading";
column.SortExpression = columnName;

grid.Columns.Add(column);

the data source...

SqlDataSource dataSource = new SqlDataSource(
    "System.Data.SqlClient",
    connectionString, 
    generatedSelectCommand);

那么这个GridView...

grid.DataSource = dataSource;
grid.DataKeyNames = mylistOfKeys;
grid.DataBind();

目前,当用户点击列标题时,我希望它可以排序列数据,但是什么也没有发生。有人知道我漏掉了什么吗?

如果有更好的方法,那就更好了,因为我觉得这看起来很混乱!

4个回答

6

在排序处理程序中的 DataBind() 调用之前,您也可以重新分配 datasource.SelectCommand。像这样:

protected void gvItems_Sorting(object sender, GridViewSortEventArgs e)
{
    GridView gv = (GridView)sender;
    SqlDataSource ds = (SqlDataSource)gv.DataSource;
    ds.SelectCommand = ds.SelectCommand + " order by " 
        + e.SortExpression + " " + GetSortDirection(e.SortDirection);
    gvItems.DataSource = ds;
    gvItems.DataBind();
}

string GetSortDirection(string sSortDirCmd)
{
    string sSortDir;
    if ((SortDirection.Ascending == sSortDirCmd))
    {
        sSortDir = "asc";
    }
    else
    {
        sSortDir = "desc";
    }
    return sSortDir;
}

我希望这可以帮到你。如果你需要额外的帮助来实现它,请告诉我。
祝愉快!

4

首先需要添加一个事件:

<asp:GridView AllowSorting="True" OnSorting="gvName_Sorting" ...

然后该事件看起来像这样:
protected void gvName_Sorting( object sender, GridViewSortEventArgs e )
{
    ...
    //rebind gridview
}

你基本上需要重新获取你的数据。

你说得对,看起来很混乱,有一个更好的方法:ASP.Net MVC

不幸的是,这是一个截然不同的页面模型。


0

迟做总比不做好?

对于Keith的建议,我有一些补充,基本上是正确的。

事实上,你必须在gridView_Sorting事件中处理排序。 例如,在Page_Load事件中没有必要提前DataBind() GridView。在那里,你只需要调用GridView.Sort()方法而不是.DataBind()。以下是具体步骤:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then

        Me.gridView.Sort(Request.QueryString("sortExpression"), Request.QueryString("sortDirection"))

    End If

End Sub

接下来让我们看一下gridView_Sorting事件。

在这里,您必须将数据源推向正确的排序方式。GridView本身不处理此操作(至少在这种情况下不处理)。

Protected Sub gridView_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles gridView.Sorting
    If IsPostBack Then
        e.Cancel = True
        Dim sortDir As SortDirection = SortDirection.Ascending
        If e.SortExpression = Me.Q_SortExpression And Me.Q_SortDirection = SortDirection.Ascending Then
            sortDir = SortDirection.Descending
        End If
        RedirectMe(e.SortExpression, sortDir)
    Else
        Dim sortExpr As String = e.SortExpression + " " + IIf(e.SortDirection = SortDirection.Ascending, "ASC", "DESC")
        Dim dv As System.Data.DataView = Me.dsrcView.Select(New DataSourceSelectArguments(sortExpr))
        Me.gridView.DataSource = dv
        Me.gridView.DataBind()
    End If
End Sub

不需要在数据源中编写任何排序功能,例如将排序参数传递给存储过程。所有排序都在上述代码片段中进行。

此外,最好将gridView.EnableViewState切换为False,这会使页面对网络流量和浏览器更加轻便。可以在页面回发时完全重新创建网格。

祝您有美好的一天!

Martin


0

我不确定这个问题,但如果您使用标准的SqlDataSource并且单击字段以根据该字段排序,则SqlDataSource将再次填充数据并重新绑定到网格。因此,排序不会在客户端上发生,而且只能在SQLDataSource的SelectMethod不是DataReader时进行。

处理排序事件时,您是否重新创建SqlDataSource并将其重新绑定到GridView?您可以将排序字段和方向放入生成的SelectCommand中吗?或者将其放入SQLDataSource的SortParameterName属性中?

我非常确定您必须将SqlDataSource重新绑定到网格,并且由于您是即时创建它的,因此必须再次填充它。


目前我完全不处理排序事件,而是让它保持默认行为。但是,我已经检查过在排序事件中SortExpression和SortDirection是合理的,而且不为空。数据源在回发时重新绑定到网格。 - Ben L
您应该像Keith提到的那样处理事件。使用标准SqlDataSource控件可以自动完成,但在这种情况下,您也需要自己注意处理它。 - Biri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接