Sunday, March 6, 2011

Gridview Sorting with Up and Down Icons, Paging

There are lot of articles on web which explains paging and sorting, there are 2 main reasons which differs this article from other articles. They are 1)Integrating the code to insert up and down arrows after sorting 2) Export a gridview with multiple pages to a single excel sheet without loss of colors and CSS.

Using the code

gridvew_RowCreated
At first we will declare some boolean variables which we will use in different methods of our page. Rowcreated event is fired everytime when a gridvew is loaded. So on page load also this event will fire up, so we have to mention conditions such that Up and Down icons wont show up immediately. This can be done simply by taking some bool variables.
Collapse
//1) Declaring the variables and Adding the RowCreated Event
  public static bool isSort = false;
        public static bool isAscend = false;
        private const string ASCENDING = " ASC";
        private const string DESCENDING = " DESC";
        public static bool showImage = false;
       
        protected void Page_Load(object sender, EventArgs e)
        {

        }
                 protected void grdiview_RowCreated(object sender,GridViewRowEventArgs e)
        {
            int sortColumnIndex = 0;

            if (e.Row.RowType == DataControlRowType.Header)
                sortColumnIndex = GetSortColumnIndex();

            if (sortColumnIndex != 1)
            {
                AddSortImage(sortColumnIndex, e.Row);
            }

        }
GetSortColumnIndex()
We have to get the index of the column for which sorting needs to be implemented. For this we need to write a method which will return the value GetSortColumnIndex() method will return 1 or -1 if column is clicked for sorting. If the cloumn is clicked for the first time it will return -1 which will add image to column. If the column already has an icon it will return that columnIndex.
Collapse
// 2) Adding a method which will return the Index of the column selected
            protected int GetSortColumnIndex()
        {


            foreach (DataControlField field in grdDateRangeReport.Columns)
            {
                if (field.SortExpression == grdDateRangeReport.SortExpression)
                    return grdiview.Columns.IndexOf(field);
                else
                    return -1;
            }
            return -1;
        }
       


  
AddSortImage()
This Method will take columnIndex, HeaderRow(the row for which the icon should be added) as parameters and then adds or changes the icon accordigly. This method should not be called on inital loading of gridview because the view state will be null and it may throw a null reference error. So we have to set a boolean variable which will allow the method to take action after sorting is clicked.
Collapse
//3) Adding the SortImage Method
protected void AddSortImage(int columnIndex, GridViewRow HeaderRow)
        {
            Image sortImage = new Image();

            if (showImage) // this is a boolean variable which should be false 
            {            //  on page load so that image wont show up initially.

                if (ViewState["sortDirection"].ToString() == "Ascending")
                {
                    sortImage.ImageUrl = "~/Images/up.gif";
                    sortImage.AlternateText = " Ascending Order";
                }

                else
                {
                    sortImage.ImageUrl = "~/Images/down.gif";
                    sortImage.AlternateText = " Descending Order";
                }

                HeaderRow.Cells[0].Controls.Add(sortImage);
            }

        }
 
PageIndexChanging Event
Collapse
protected void gridview_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            gridview.PageIndex = e.NewPageIndex;

            if (!isSort) // this will get exectued if user clicks paging
            {            // before sorting istelf

                gridview.DataSource = null; // I gave Datasource as null for
                 gridview.DataBind();     //instance. Provide your datasource
                                          // to bind the data
            }

            else if (isAscend)// this will get exectued if user clicks paging
                              // after cliclking ascending order
            {

   // I am passing only "DateRequest" as sortexpression for instance. because
  // i am implementing sorting for only one column. You can generalize it to 
  // pass that particular column on sorting.
                SortGridView("DateRequest", ASCENDING);
                
            }
            else // this will get exectued if user clicks paging
                              // after cliclking descending order

            {
                SortGridView("DateRequest", DESCENDING);

            }


        }
gridview_RowDataBound Event
Collapse
// to set the height of row.
protected void gridview_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            e.Row.Height = Unit.Pixel(20);

        }
GridViewSortDirection Property
Collapse
private SortDirection GridViewSortDirection
        {

            get
            {

                if (ViewState["sortDirection"] == null)

                    ViewState["sortDirection"] = SortDirection.Ascending;


                return (SortDirection)ViewState["sortDirection"];

            }

            set { ViewState["sortDirection"] = value; }

        }
SortGridView()
Collapse
protected void SortGridView(string sortExpression, string direction)
        {
           
            DataTable dataTable = gridview.DataSource as DataTable;


            if (dataTable != null)
            {
                DataView dataView = new DataView(dataTable);
                dataView.Sort = sortExpression + direction;

                gridview.DataSource = dataView;
                gridview.DataBind();
            }

        }
gridview_Sorting Event
This is an example for manual sorting. It is simple to implement. The only thing we have to make sure is, the application will implement Ascending order at first and as soon as gridview column is sorted in ascending order, we have to change the SortDirection to Descending or else when we click to sort next time it will again do Ascend
Collapse
protected void gridview_Sorting(object sender, GridViewSortEventArgs e)
        {
            isSort = true;

            string sortExpression = e.SortExpression;

            ViewState["SortExpression"] = sortExpression;
            showImage = true;

            if (GridViewSortDirection == SortDirection.Ascending)
            {
                isAscend = true;

                SortGridView(sortExpression, ASCENDING);
                GridViewSortDirection = SortDirection.Descending;

            }

            else
            {
                isAscend = false;
                SortGridView(sortExpression, DESCENDING);
                GridViewSortDirection = SortDirection.Ascending;

            }

        }
btnExport_Click
There are cases where we have implemented paging for gridview and it contains many pages. When you export it to excel, it will export only first page. Main cause for this is we kept "AllowPaging=True" in the design and bind the grid. So, the code just exports the first page as a html. We can overcome this by using simple logic, in the "btnExportExcel_Click" event bind the grid again by making the "AllowPaging" false, export it to excel and after exporting again enable "AllowPaging" to true, bind the grid. See the below code which explains the logic.
Collapse
protected void btnExportExcel_Click(object sender, EventArgs e)
        {
            
           grdDateRangeReport.DataSource = null; //Give Your Datasource
                                                //for time being i gave the 
                                                // datasource as  null
                gridview.AllowPaging = false;
                gridview.DataBind();

            
            Response.ClearContent();
            Response.AddHeader("content-disposition", "attachment; filename=MyReports.xls");

            Response.ContentType = "application/excel";

            StringWriter sw = new StringWriter();
            HtmlForm fm = new HtmlForm();
            HtmlTextWriter htw = new HtmlTextWriter(sw);

            Controls.Add(fm);

            fm.Controls.Add(gridview);
            fm.RenderControl(htw);


            Response.Write(sw.ToString());

            Response.End();
// making the Allowpaging true again and binding it.
            gridview.AllowPaging = true;
            gridview.DataBind();
        }

No comments:

Post a Comment