Как сортировать столбцы в ASP.NET GridView при использовании пользовательского источника данных?

Я не могу заставить свой GridView разрешить пользователю сортировать столбец данных, когда я использую пользовательский SqlDataSource.

У меня есть GridView, в котором код в ссылке ASP на него в 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);

источник данных...

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

затем сетка...

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

На данный момент ничего не происходит, когда пользователь щелкает заголовок столбца, когда я ожидаю, что он отсортирует данные столбца. У кого-нибудь есть идеи, что мне не хватает?

Если есть более приятный способ сделать это, это тоже было бы полезно, так как это выглядит грязно для меня!


person Ben L    schedule 26.09.2008    source источник


Ответы (4)


Сначала нужно добавить событие:

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

Тогда это событие выглядит так:

protected void gvName_Sorting( object sender, GridViewSortEventArgs e )
{
    ...
    //rebind gridview
}

Вы в основном должны получить свои данные снова.

Вы правы, что это выглядит грязно, и есть лучший способ: ASP.Net MVC.

К сожалению, это совершенно другая модель страницы.

person Keith    schedule 26.09.2008

Вы также можете просто переназначить datasource.SelectCommand перед вызовом DataBind() в обработчике Sorting. Что-то вроде этого:

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;
}

Я надеюсь, что это поможет. Дайте мне знать, если вам нужна дополнительная помощь для его реализации.

Наслаждаться!

person Mike    schedule 13.12.2010

Я не уверен в этом, но если вы используете стандартный SqlDataSource и щелкаете поле для сортировки в соответствии с этим полем, SqlDataSource снова заполняется данными, и они повторно привязываются к сетке. Таким образом, сортировка не происходит на стороне клиента, а также может выполняться только тогда, когда метод select для SQLDataSource не является DataReader.

При обработке события сортировки вы воссоздаете SqlDataSource и повторно привязываете его к GridView? Можете ли вы поместить поле сортировки и направление в generateSelectCommand, который вы используете? Или поместите его в свойство SortParameterName источника SQLDataSource?

Я абсолютно уверен, что вам нужно повторно привязать SqlDataSource к сетке, и, поскольку вы создаете его на лету, вам нужно заполнить его снова.

person Biri    schedule 26.09.2008
comment
На данный момент я вообще не обрабатываю событие сортировки и оставляю его поведение по умолчанию. Однако я проверил, что в событии сортировки SortExpression и SortDirection являются чем-то разумным, а не пустым. Источник данных повторно привязывается к сетке при отправке обратно, - person Ben L; 26.09.2008
comment
Вы должны обработать событие, как упоминал Кит. Со стандартным элементом управления SqlDataSource это делается автоматически, но в этом случае вы также должны позаботиться об этом самостоятельно. - person Biri; 26.09.2008

Лучше поздно, чем никогда?

Некоторое дополнение к предложению Кита, которое в принципе правильное.

Правда в том, что вам приходится иметь дело с сортировкой по событию gridView_Sorting. Нет необходимости использовать DataBind() для GridView ранее, например, в событии Page_Load. Там вы должны вызывать только метод 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, что делает страницу намного легче для сетевого трафика, а также для браузера. Можно сделать это, поскольку сетка полностью воссоздается всякий раз, когда страница отправляется обратно.

Хорошего дня!

Мартин

person Martin    schedule 03.06.2010