Come ordinare le colonne in un ASP.NET GridView se si utilizza un DataSource personalizzato?

StackOverflow https://stackoverflow.com/questions/138412

Domanda

Non riesco a far sì che GridView consenta a un utente di ordinare una colonna di dati quando utilizzo un SqlDataSource personalizzato.

Ho un GridView in cui il codice nel riferimento ASP ad esso in HTML è minimo:

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

Nel code-behind allego un SqlDataSource creato in modo dinamico (le colonne che contiene non sono sempre le stesse, quindi l'SQL utilizzato per crearlo viene costruito in fase di esecuzione). Ad esempio:

Ho impostato le colonne ...

BoundField column = new BoundField();
column.DataField = columnName;
column.HeaderText = "Heading";
column.SortExpression = columnName;

grid.Columns.Add(column);

l'origine dati ...

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

quindi la visualizzazione griglia ...

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

Al momento non accade nulla quando un utente fa clic sull'intestazione di una colonna quando mi aspetto che ordina i dati della colonna. Qualcuno ha qualche idea di cosa mi sto perdendo?

Se c'è un modo migliore per farlo, sarebbe utile anche perché mi sembra disordinato!

È stato utile?

Soluzione

Per prima cosa devi aggiungere un evento:

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

Quindi quell'evento appare come:

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

Fondamentalmente devi recuperare nuovamente i tuoi dati.

Hai ragione a sembrare disordinato e c'è un modo migliore: ASP.Net MVC

Purtroppo questo è un modello di pagina drasticamente diverso.

Altri suggerimenti

È anche possibile riassegnare l'origine dati.SelectCommand prima della chiamata DataBind () nel gestore di ordinamento. Qualcosa del genere:

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

Spero che questo aiuto. Fammi sapere se hai bisogno di ulteriore aiuto per implementarlo.

Enjoy!

Non ne sono sicuro, ma se si utilizza un SqlDataSource standard e si fa clic su un campo per ordinare in base a quel campo, SqlDataSource viene nuovamente popolato con i dati e viene rimbalzato sulla griglia. Pertanto, l'ordinamento non avviene sul lato client e può essere eseguito solo quando il metodo select di SQLDataSource non è DataReader.

Quando si gestisce l'evento di ordinamento, si ricrea SqlDataSource e lo si rimbalza su GridView? Puoi mettere il campo di ordinamento e la direzione in generateSelectCommand, che usi? O metterlo nella proprietà SortParameterName di SQLDataSource?

Sono assolutamente sicuro che devi rimbalzare SqlDataSource sulla griglia e, dato che lo crei al volo, devi popolarlo di nuovo.

Meglio tardi che mai?

Qualche aggiunta per il suggerimento di Keith che è fondamentalmente quello giusto.

La verità è che devi occuparti dell'ordinamento sull'evento gridView_Sorting. Non è necessario DataBind () GridView in precedenza, ad esempio nell'evento Page_Load. Lì dovresti solo chiamare il metodo GridView.Sort () invece di .DataBind (). Ecco come va:

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

Ora diamo un'occhiata all'evento gridView_Sorting.

Lì devi spingere l'origine dati nell'ordinamento corretto. GridView stesso non lo gestisce (almeno in questo caso).

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

Non è necessario codificare alcuna funzionalità di ordinamento nell'origine dati come passare i parametri di ordinamento alla procedura memorizzata. Tutto l'ordinamento avviene nelle parti di codice sopra riportate.

Inoltre, è bene che gridView.EnableViewState sia impostato su False, il che rende la pagina molto più leggera per il traffico di rete e anche per il browser. Puoi farlo poiché la griglia viene ricreata interamente ogni volta che la pagina viene posticipata.

Buona giornata!

Martin

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top