ITfjernundervisning

ASP.NET / Dataset og datagrid objektet / Sortering

Sortering

Vi bruger DataView objektet til at klare sorteringen.

Igen er der en række ting vi skal lave for at få det til at virke

  • Sorting skal sættes til true på vores datagrid (det skulle være til at finde ud af:-))
  • Vi skal give besked om hvilken routine der skal kaldes ved sortering - det kan igen gøres pr. håndkraft, eller gennem hændelsesstyringen. Kommandoen skulle være til at gætte:
    onSortCommand="DoSort"
  • Og endelig skal vi have skrevet selve routinen. Læg mærke til at vi bruger en viewstate variabel til at holde sorteringen fra runde til runde

 

Objekt kodning

Vi skal have lavet en udvidelse af vores klasse, så den kan håndtere sorteringen:

C#:

public DataView ProjektListe(string sortfield, string sortorder)
{
 DataView dview = _Projekter.Tables[0].DefaultView;
 dview.Sort = sortfield + " " + sortorder;
 return dview;
}

VB:

Public Function ProjektListe(ByVal sortfield As String, ByVal sortorder As String) As DataView
    Dim dview As DataView = _Projekter.Tables(0).DefaultView
    dview.Sort = sortfield + " " + sortorder
    Return dview
  End Function

Det skal laves som en ekstra metode!

I codebehind filen laver vi et par egenskaber på pageobjektet, lidt ændringer i DoDataBind() og en eventhandler. Læg mærke til, hvordan de to metoder fra projekter klassen bliver brugt.

C#:

public string sortfield
{
 get { return (string)ViewState["sortfield"];}
 set { ViewState["sortfield"] = value;}
}

public string sortorder
{
 get { return (string)ViewState["sortorder"];}
 set { ViewState["sortorder"] = value;}
}

private void dgridProjekter_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
{
 dgridProjekter.CurrentPageIndex = e.NewPageIndex;
 DoDataBind();
}

private void dgridProjekter_SortCommand(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
 if (sortfield == e.SortExpression.ToString())
  if (sortorder == "ASC")
   sortorder = "DESC";
  else
   sortorder = "ASC";
 else
  sortorder = "ASC";
 sortfield = e.SortExpression.ToString();
 DoDataBind();
}

private void DoDataBind()
{
 if (sortfield == null)
  dgridProjekter.DataSource = _Projekter.ProjektListe();
 else
  dgridProjekter.DataSource = _Projekter.ProjektListe(sortfield, sortorder);
 DataBind();
}

VB:

  Dim _Projekter As Projekter = New Projekter
  Public Property sortfield() As String
    Get
      Return ViewState("sortfield")
    End Get
    Set(ByVal Value As String)
      ViewState("sortfield") = Value
    End Set 
  End Property

  Public Property sortorder() As String
    Get
      Return ViewState("sortorder")
    End Get
    Set(ByVal Value As String)
      ViewState("sortorder") = Value
    End Set
  End Property

  Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
      DoDatabind()
    End If
  End Sub

  Private Sub DoDatabind()
    If sortfield Is Nothing Then
      dgData.DataSource = _Projekter.ProjektListe()
    Else
      dgData.DataSource = _Projekter.ProjektListe(sortfield, sortorder)
    End If
    dgData.DataBind()
  End Sub

  Private Sub dgData_SortCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) Handles dgData.SortCommand
    If sortfield = e.SortExpression Then
      If sortorder = "ASC" Then
        sortorder = "DESC"
      Else
        sortorder = "ASC"
      End If
    Else
      sortorder = "ASC"
    End If
    sortfield = e.SortExpression
    DoDatabind()
  End Sub

 

Klassisk kodning

Der er sket ændringer i DoDatabind routinen, tilføjet en variabel i toppen og skrevet en eventhandler.

VB.NET

Dim strSortOrder As String

    Private Sub dgridAndeby_SortCommand(ByVal ...
        strSortOrder = e.SortExpression.ToString()
        ViewState("SortOrder") = strSortOrder
        DoDatabind()
    End Sub

    Private Sub DoDatabind()
        Dim dsetAndeby As New Dataset()
        dsetAndeby.ReadXml(Server.MapPath("Andeby.xml"))
        Dim objDataView As DataView
        strSortOrder = ViewState("SortOrder")
        objDataView = dsetAndeby.Tables(0).DefaultView
        objDataView.Sort = strSortOrder
        dgridAndeby.DataSource = objDataView
        dgridAndeby.DataBind()
    End Sub

C#

namespace Udviklingcsharp.ASP.NET_II_kursus
{
 public class _3_sortering : System.Web.UI.Page
 {
  protected System.Web.UI.WebControls.DataGrid dgridAndeby;
  DataSet dsetAndeby = new DataSet();
  String strSortOrder = "";
  private void Page_Load(object sender, System.EventArgs e)
  {
    if (!IsPostback) {
      ViewState["SortOrder"] = "";
      DoDatabind();
    }
  }

  private void DoSort(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
  {
   strSortOrder = e.SortExpression.ToString();
   ViewState["SortOrder"] = strSortOrder;
   DoDatabind();
  }

  private void DoDatabind()
  {
   DataSet dsetAndeby = new DataSet();
   dsetAndeby.ReadXml(Server.MapPath("Andeby.xml"));
   DataView objDataView;
   strSortOrder = ViewState["SortOrder"].ToString();
   objDataView = dsetAndeby.Tables[0].DefaultView;
   objDataView.Sort = strSortOrder;
   dgridAndeby.DataSource = objDataView;
   dgridAndeby.DataBind();
  }
 }
}

Som vi har implementeret løsningen her sorterer den automatisk kolonnerne faldende. Man kan styre sorteringsrækkefølgen ved at tilføje et ASC eller et DESC i enden af strSortOrder, men skal man lave et datagrid, der sorterer korrekt både op og ned og på flere kolonner skal man nok sætte en enkelt eftermiddag af til det. Det er ikke kodemæssigt svært, men man skal lige tænke logikken igennem inden man går igang.

Sortering af datoer er altid en udfordring. Mange års erfaring har lært mig, at man altid skal gemme datoer i yyyy-mm-dd formatet - så virker sortering umiddelbart. I et datagrid kan man så, hvis man snor sig lidt, skifte formateringen med teksten {0:d} i dataformatting expression på den kolonne datoen står i (man skal jo have overbevist datagrid'et om, at det faktisk er en dato).

String.Format("{0:d}", Convert.ToDateTime(Container.DataItem("Foedselsdato")))

Brug hellere tiden på at kigge lidt på den RowFilter metode, som dataview objektet også har - det giver nogle interessante muligheder.


Når du har betalt for kurset får du adgang til øvelser til hver lektion.
Og når du har fået godkendt din besvarelse får du desuden adgang til mine løsningsforslag med ekstra tips og trix.