Sunday 20 May 2012

Rendering GridView Rows when scrolling down using AJAX concept - Part 2

In previous post, We had seen how to render the GridView rows from the server and show while scrolling the GridView.

This is a continuation of that post which discuss the second implementation. I had explained the background of this implementation in the first post. So, It is better to read the post for understanding how it is been implemented (but there is no dependency in the code).

Second Implementation
In the previous implementation, the new records are fetched and adds at the end of the GridView while scrolling down to the end of the GridView. In this implementation we will discuss how to show a progress message at the top corner of the screen when the server is fetching the records. So the user can get to know the server is under processing and has to wait for the response.

The use case will be the same as the first method additionally there will be a message for each server calls from the Javascript using AJAX. So the use case would be
  1. Show list of records in a GridView with all sort of customizations possible (such as colors, data formatting etc.,).
  2. The GridView should show all the records in a single page without having pagination.
  3. The GridView should have a scroll bar to scroll and see the records up and down.
  4. Initially the GridView should show only first two pages on the screen (or decided by the programmer on the code).
  5. When user scrolls down to see last records, the page should fetch the next 10 records (or decided by programmer in the code) and add with the records at the last shown in the GridView.
  6. When user scrolls further down to see the newly added records, the page should fetch the next 10 records and add at the last to the GridView. This repeats until last record reached.
  7. When the server is fetching the records from the database, the page should show a process message such as "Working on your Request" on the top-right corner. Once the records are fetched and shown at the end of the GridView, the message should hidden.
I have given two example for this implementation,
  1. Without sorting option on the GridView
  2. With Sorting on the GridView.

Implementation without Sorting in GridView

The ASPX script (ProcessMessage.aspx)
<div id="GridViewContainer" style="width:100%;height:400px;" onscroll="RefreshRows(this)" >
    <asp:GridView ID="grdViewProducts" CssClass="ViewProducts" runat="server" AutoGenerateColumns="False" TabIndex="1" 
        AllowPaging="false" DataKeyNames="ProductID" Width="100%" GridLines="Both" CellPadding="3" 
        AllowSorting="false" BackColor="White">
        <Columns>
            <asp:BoundField DataField="ProductName" HeaderText="Product Name" 
                SortExpression="ProductName">
            <ItemStyle Width="26%" />
            </asp:BoundField>
            <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                SortExpression="CategoryName" >
            <ItemStyle Width="17%" />
            </asp:BoundField>
            <asp:BoundField DataField="QuantityPerUnit" HeaderText="Quantity/Unit" 
                SortExpression="QuantityPerUnit" >
            <ItemStyle Width="17%" />
            </asp:BoundField>
            <asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" 
                SortExpression="UnitPrice" DataFormatString="{0:#0.00}" >
            <ItemStyle Width="10%" />
            </asp:BoundField>
            <asp:BoundField DataField="UnitsInStock" HeaderText="Units In Stock" 
                SortExpression="UnitsInStock" >
            <ItemStyle Width="10%" />
            </asp:BoundField>
            <asp:BoundField DataField="UnitsOnOrder" HeaderText="Units On Order" 
                SortExpression="UnitsOnOrder" >
            <ItemStyle Width="10%" />
            </asp:BoundField>
            <asp:BoundField DataField="ReorderLevel" HeaderText="Reorder Level" 
                SortExpression="ReorderLevel" >
            <ItemStyle Width="10%" />
            </asp:BoundField>
        </Columns>
        <EmptyDataTemplate>
            <div>
                <p style="color:Red">No search results found.</p>
            </div>
        </EmptyDataTemplate>
        <PagerSettings Position="Bottom" />
        <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />
        <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />
        <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />
        <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />
        <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" />
        <AlternatingRowStyle BackColor="#F7F7F7" />
        <SortedAscendingCellStyle BackColor="#F4F4FD" />
        <SortedAscendingHeaderStyle BackColor="#5A4C9D" />
        <SortedDescendingCellStyle BackColor="#D8D8F0" />
        <SortedDescendingHeaderStyle BackColor="#3E3277" />
    </asp:GridView>
    <div id="divChildGrid">
    </div>
</div>
<input id="hiddenInitialNoOfPageLoad" type="hidden" value="0" runat="server" />
<input id="hiddenTotalRecords" type="hidden" value="0" runat="server" />
<input id="hiddenPageRecordCount" type="hidden" value="0" runat="server" />
The C# Code behind (ProcessMessage.aspx.cs)
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        hiddenInitialNoOfPageLoad.Value = "2";
        hiddenPageRecordCount.Value = ConfigurationManager.AppSettings["PageRecordCount"].ToString();
        BindGrid();
    }
}
private void BindGrid()
{
    // Defining int variable to get the Total Record Count from Data layer
    int totalRecordCount = 0;

    // Getting how many records required to show in the Grid per page
    int intPageRecordCount = Convert.ToInt32(hiddenPageRecordCount.Value) * 2; // I am fetching 3 pages at first time

    ProductDAO objProductDAO = new ProductDAO();

    IList<ProductView> ProductViewList = objProductDAO.GetProducts(1, intPageRecordCount, string.Empty, SortType.Ascending, out totalRecordCount); // Getting First three pages
    //Adding one empty row for just to show the grid
    if (ProductViewList.Count == 0)
        ProductViewList.Add(new ProductView());

    grdViewProducts.DataSource = ProductViewList;
    grdViewProducts.DataBind();

    // Assign the Total Record count to 
    hiddenTotalRecords.Value = totalRecordCount.ToString();
}
The Javascript (ProcessMessage.aspx)
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5") != -1) ? 1 : 0;
var xmlHttp;
var varStartAJAXPage = 3;
var varPageOnBehind = 0;

function pageLoad() {
    GetChildGrid(varStartAJAXPage);
    ShowProgress('Hide');
}
window.onload = pageLoad;

/* This function requests the HTTPRequest, will be used to render the Dynamic content html markup 
* and it will call HandleResponse to handle the response
*/
function GetChildGrid(pageId) {

    // Get the Div
    var childGridDiv = document.getElementById("divChildGrid");

    if (childGridDiv) {
        // If the Child Grid is not fetched, then go and fetch it.
        var varTotalRecords = document.getElementById('<%= hiddenTotalRecords.ClientID %>').value;
        var varPageRecordCount = document.getElementById('<%= hiddenPageRecordCount.ClientID %>').value;

        if ((pageId > 0) && (parseInt(varTotalRecords) > (parseInt(varPageRecordCount) * (parseInt(pageId) - 1)))) {

            var url = 'RowsBuilder.aspx?PageId=' + pageId +
                        '&PageRecordsCount=' + varPageRecordCount;
            xmlHttp = createAjaxObject();
            if (xmlHttp) {
                xmlHttp.open('get', url, true);
                xmlHttp.onreadystatechange = function () {
                    HandleResponse(pageId);
                }
                varPageOnBehind = varStartAJAXPage;
                xmlHttp.send(null);
            }
        }
    }
}
function RefreshRows(div) {
    if (varStartAJAXPage - varPageOnBehind > 0) {
        if ((div.scrollHeight - (div.scrollTop + div.offsetHeight)) < 200) {
            varPageOnBehind = varStartAJAXPage;
            GetChildGrid(varStartAJAXPage);
        }
    }
}
/* This function is used to handler the http response */
function HandleResponse(pageId) {

    var childGridDiv = document.getElementById("divChildGrid");

    // If Response completed
    if (xmlHttp.readyState == 4) {

        if (xmlHttp.status == 200) {

            // Here is the response
            var str = xmlHttp.responseText;

            var divRows = document.createElement('div');
            divRows.innerHTML = str;

            childGridDiv.appendChild(divRows);
            varStartAJAXPage++;

            xmlHttp.abort();

            ShowProgress('Hide');
        }
        else {
            ShowProgress('Show');
        }
    }
    else {
        ShowProgress('Show');
    }
}

function ShowProgress(ShowFlag)
{
    if (ShowFlag == 'Show')
    {
        var progressDiv;
        if (!document.getElementById('divProgress'))
        {
                    
            progressDiv = document.createElement("div");
            progressDiv.setAttribute("id", 'divProgress');
            progressDiv.className = "ProgressStyle";
            
            var lblProcessMessage = document.createTextNode("Working on your Request");

            progressDiv.appendChild(lblProcessMessage);
            
            progressDiv.style.left = (screen.width - 160) + "px";
            progressDiv.style.top = "3px";
            progressDiv.style.position = "absolute";
            progressDiv.style.zIndex = 10000;
            document.body.appendChild(progressDiv);
            
        }
        else
            progressDiv = document.getElementById('divProgress');
            
        var scrollpos = getScrollingPosition();
        progressDiv.style.left = (screen.width - 265) + "px";
        progressDiv.style.top = scrollpos[1] + "px";
        progressDiv.style.position = "absolute";
        progressDiv.style.zIndex = 2;
        progressDiv.style.visibility = "visible";
        
    }
    if (ShowFlag == 'Hide')
    {
        progressDiv = document.getElementById('divProgress');
        progressDiv.style.visibility = "hidden";
    }
}
function getScrollingPosition() {
    var position = [0, 0];
    if (typeof window.pageYOffset != 'undefined') {
        position = [window.pageXOffset, window.pageYOffset];
    }
    else
        if (typeof document.documentElement.scrollTop != 'undefined' &&
            document.documentElement.scrollTop > 0
    ) {
            position = [document.documentElement.scrollLeft,
                    document.documentElement.scrollTop
                    ];
        }
        else
            if (typeof document.body.scrollTop != 'undefined') {
                position = [document.body.scrollLeft, document.body.scrollTop];
            }
    return position;
}
/* function to create Ajax object */
function createAjaxObject() {
    var ro;
    var browser = navigator.appName;
    if (browser == "Microsoft Internet Explorer") {
        if (xmlHttp != null) {
            xmlHttp.abort();
        }
        ro = new ActiveXObject("Microsoft.XMLHTTP");
    }
    else {
        if (xmlHttp != null) {
            xmlHttp.abort();
        }
        ro = new XMLHttpRequest();
    }
    return ro;
}

/* Get the XML Http Object */
function GetXmlHttpObject(handler) {
    var objXmlHttp = null;
    if (is_ie) {
        var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';

        try {
            objXmlHttp = new ActiveXObject(strObjName);
            objXmlHttp.onreadystatechange = handler;
        }
        catch (e) {
            alert('Object could not be created');
            return;
        }
    }
    return objXmlHttp;
}

function xmlHttp_Get(xmlhttp, url) {
    xmlhttp.open('GET', url, true);
    xmlhttp.send(null);
}
The CSS Stylesheet (ProcessMessage.aspx)
#GridViewContainer
{           
    overflow: auto;
}
.ViewProducts
{
    border-top-style:solid;
    border-left-style:solid;
    border-right-style:solid;
    border-bottom-style:none;
}
.ViewChildProducts
{
    border-top-style:solid;
    border-left-style:solid;
    border-right-style:solid;
    border-bottom-style:none;
}
.ProgressStyle
{
    width:170px;
    padding-left:10px;
    height:20px;
    color:Black;
    background-color:#ffe0b3;
    border:gray 0px solid;
}
The Respondent ASPX script (RowsBuilder.aspx)
<asp:GridView ID="grdAJAXViewProducts" runat="server" ShowHeader="false" ShowFooter="false"
    AutoGenerateColumns="False" TabIndex="1" AllowPaging="false" DataKeyNames="ProductID"
    Width="100%" GridLines="Both" CellPadding="3" AllowSorting="True"
    BackColor="White" CssClass="ViewProducts">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product Name" 
            SortExpression="ProductName" >
        <ItemStyle Width="26%" />
        </asp:BoundField>
        <asp:BoundField DataField="CategoryName" HeaderText="Category" 
            SortExpression="CategoryName" >
        <ItemStyle Width="17%" />
        </asp:BoundField>
        <asp:BoundField DataField="QuantityPerUnit" HeaderText="Quantity/Unit" 
            SortExpression="QuantityPerUnit" >
        <ItemStyle Width="17%" />
        </asp:BoundField>
        <asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" 
            SortExpression="UnitPrice" DataFormatString="{0:#0.00}" >
        <ItemStyle Width="10%" />
        </asp:BoundField>
        <asp:BoundField DataField="UnitsInStock" HeaderText="Units In Stock" 
            SortExpression="UnitsInStock" >
        <ItemStyle Width="10%" />
        </asp:BoundField>
        <asp:BoundField DataField="UnitsOnOrder" HeaderText="Units On Order" 
            SortExpression="UnitsOnOrder" >
        <ItemStyle Width="10%" />
        </asp:BoundField>
        <asp:BoundField DataField="ReorderLevel" HeaderText="Reorder Level" 
            SortExpression="ReorderLevel" >
        <ItemStyle Width="10%" />
        </asp:BoundField>
    </Columns>
    <PagerSettings Position="Bottom" />
    <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />
    <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />
    <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />
    <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />
    <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" />
    <AlternatingRowStyle BackColor="#F7F7F7" />
    <SortedAscendingCellStyle BackColor="#F4F4FD" />
    <SortedAscendingHeaderStyle BackColor="#5A4C9D" />
    <SortedDescendingCellStyle BackColor="#D8D8F0" />
    <SortedDescendingHeaderStyle BackColor="#3E3277" />
</asp:GridView>
The Code behind file of Respondent (RowsBuilder.aspx.cs)
protected void Page_Load(object sender, EventArgs e)
{
    if ((!Page.IsPostBack) && (Request.QueryString["PageId"] != null))
    {
        Response.Clear();
        Response.ContentType = "text/xml";

        BindGrid();

        System.IO.StringWriter stringWrite = new System.IO.StringWriter();
        System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
        grdAJAXViewProducts.RenderControl(htmlWrite);
        Response.Write(stringWrite.ToString());

        Response.End();
    }
}
public override void VerifyRenderingInServerForm(Control control)
{
}
private void BindGrid()
{
    // Defining int variable to get the Total Record Count from Data layer
    int totalRecordCount = 0;
            
    string strSortExpression = string.Empty;
    SortType sortType = SortType.Ascending;

    if (Request.QueryString["SortExpression"] != null)
    {
        // Get the SortByExpression and SortType from Query String (by default, that will be updated in script)
        strSortExpression = Request.QueryString["SortExpression"].ToString().Split(",".ToCharArray())[0];
        sortType = (SortType)Enum.Parse(typeof(SortType), Request.QueryString["SortExpression"].ToString().Split(",".ToCharArray())[1], true);
    }

    // Getting how many records required to show in the Grid per page
    int intPageRecordCount = Convert.ToInt32(Request.QueryString["PageRecordsCount"].ToString());

    ProductDAO objProductDAO = new ProductDAO();

    IList<ProductView> ProductViewList = objProductDAO.GetProducts(Convert.ToInt32(Request.QueryString["PageId"].ToString()), intPageRecordCount, strSortExpression, sortType, out totalRecordCount);
    //Adding one empty row for just to show the grid
    if (ProductViewList.Count == 0)
        ProductViewList.Add(new ProductView());

    grdAJAXViewProducts.DataSource = ProductViewList;
    grdAJAXViewProducts.DataBind();
}
The Class for fetching the Data from Database (ProductDAO.cs)
public class ProductDAO
{
    public IList<ProductView> GetProducts(int currentPageNo, int pageRecordsCount, string sortBy, SortType sortType, out int totalRecordCount)
    {
        SqlConnection connection = null;
        SqlDataReader dataReader = null;

        try
        {
            IList<ProductView> productViewList = new List<ProductView>();
            connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());

            SqlDataAdapter dataAdaptor = new SqlDataAdapter("SP_GET_PRODUCTS", connection);
            dataAdaptor.SelectCommand.CommandType = System.Data.CommandType.StoredProcedure;

            dataAdaptor.SelectCommand.Parameters.Add(new SqlParameter("@CurrentPageNo", SqlDbType.Int));
            dataAdaptor.SelectCommand.Parameters["@CurrentPageNo"].Value = currentPageNo;

            dataAdaptor.SelectCommand.Parameters.Add(new SqlParameter("@PageRecordsCount", SqlDbType.Int));
            dataAdaptor.SelectCommand.Parameters["@PageRecordsCount"].Value = pageRecordsCount;

            dataAdaptor.SelectCommand.Parameters.Add(new SqlParameter("@SortBy", SqlDbType.VarChar));
            dataAdaptor.SelectCommand.Parameters["@SortBy"].Value = sortBy;

            dataAdaptor.SelectCommand.Parameters.Add(new SqlParameter("@SortType", SqlDbType.VarChar));
            dataAdaptor.SelectCommand.Parameters["@SortType"].Value = ((sortType == null) ? string.Empty : (sortType == SortType.Ascending ? "Asc" : "Desc"));

            dataAdaptor.SelectCommand.Parameters.Add(new SqlParameter("@TotalRecordCount", SqlDbType.Int));
            dataAdaptor.SelectCommand.Parameters["@TotalRecordCount"].Direction = ParameterDirection.Output;
            connection.Open();

            DataSet dataSet = new DataSet();
            dataAdaptor.Fill(dataSet);

            foreach (DataRow dataRow in dataSet.Tables[0].Rows)
            {
                ProductView productView = new ProductView();
                productView.ProductID = Convert.ToInt32(dataRow["ProductID"].ToString());
                productView.ProductName = dataRow["ProductName"].ToString();
                productView.CompanyName = dataRow["CompanyName"].ToString();
                productView.CategoryName = dataRow["CategoryName"].ToString();
                productView.QuantityPerUnit = dataRow["QuantityPerUnit"].ToString();
                productView.UnitPrice = Convert.ToDouble(dataRow["UnitPrice"].ToString());
                productView.UnitsInStock = Convert.ToInt32(dataRow["UnitsInStock"].ToString());
                productView.UnitsOnOrder = Convert.ToInt32(dataRow["UnitsOnOrder"].ToString());
                productView.ReorderLevel = Convert.ToInt32(dataRow["ReorderLevel"].ToString());

                productViewList.Add(productView);
            }
            // To make more processing time 
            //for (int i = 0; i < (1000000000/2); i++) { int b = 5 + 4 + 3 + 2 - 3; }
            totalRecordCount = Convert.ToInt32(dataAdaptor.SelectCommand.Parameters["@TotalRecordCount"].Value);
            connection.Close();

            //return
            return productViewList;
        }
        catch (Exception ex)
        {
            if (connection != null) connection.Close();
            if (dataReader != null) dataReader.Close();

            // Log
            throw ex;
        }
    }
}
The ProductView entity class
public class ProductView
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public string CompanyName { get; set; }
    public string CategoryName { get; set; }
    public string QuantityPerUnit { get; set; }
    public double UnitPrice { get; set; }
    public int UnitsInStock { get; set; }
    public int UnitsOnOrder { get; set; }
    public int ReorderLevel { get; set; }
}
public enum SortType
{
    Ascending,
    Descending
}
The Database script
Create View [dbo].[ProductView]
As
Select Products.ProductID,
  Products.ProductName,
  Suppliers.CompanyName,
  Categories.CategoryName,
  Products.QuantityPerUnit,
  Products.UnitPrice,
  Products.UnitsInStock,
  Products.UnitsOnOrder,
  Products.ReorderLevel
from Products
Join Suppliers on Suppliers.SupplierID = Products.SupplierID
Join Categories on Categories.CategoryID = Products.CategoryID
Go


CREATE PROCEDURE [dbo].[SP_GET_PRODUCTS]
@CurrentPageNo AS INT,
@PageRecordsCount AS INT,
@SortBy AS NVARCHAR(250),
@SortType AS NVARCHAR(250),
@TotalRecordCount AS INT OUTPUT
AS
 
SET NOCOUNT ON
 
DECLARE @SQL AS NVARCHAR(1000)
DECLARE @RecordsFrom AS INT
DECLARE @RecordsTo AS INT
 
-- RecordsFrom => For Ex: CurrentPage 2, PageRecordCount = 10, then (((2-1) * 10) + 1) => ((1 * 10) + 1) => 11
SET @RecordsFrom = (((@CurrentPageNo - 1) * @PageRecordsCount) + 1) 
 
-- @RecordsTo => For Ex: CurrentPage 2, PageRecordCount = 10, then (2 * 10) => 20
SET @RecordsTo = (@CurrentPageNo * @PageRecordsCount)
 
IF @SortBy = '' OR @SortBy = NULL
 SET @SortBy = 'ProductName'
 
IF @SortType = '' OR @SortType = NULL
 SET @SortType = 'Asc'
 
-- Getting the Total Record Count
SELECT @TotalRecordCount = COUNT(*) FROM ProductView
 
-- Getting the records for a particular page
SET @SQL = 
  'SELECT * FROM ' +
  '( ' +
  ' SELECT ' +
  '  ROW_NUMBER() OVER (ORDER BY ' + @SortBy + ' ' +  @SortType + ') AS RowNumber, *' +
  ' FROM ProductView ' +
  ') AS RECORDS ' +
  'Where RowNumber between ' + CAST(@RecordsFrom AS VARCHAR) + ' and ' + CAST(@RecordsTo AS VARCHAR)
 
EXECUTE(@SQL)

Implementation with Sorting in GridView

The source code for this implementation is same except the below code

Add below Style Sheet
th a.sortdown
{
 background: url(../../images/up.png) left center no-repeat;
 padding-left: 22px;
}
th a.sortup
{
 background: url(../../images/down.png) left center no-repeat;
 padding-left: 22px;
}
The ASPX Script (ProcessMessageSorting.aspx)

Add one hidden control hiddenSortExpression in the Page and add sorting event for the GridView.
<div id="GridViewContainer" style="width:100%;height:400px;" onscroll="RefreshRows(this)" >
    <asp:GridView ID="grdViewProducts" CssClass="ViewProducts" runat="server" 
        AutoGenerateColumns="False" TabIndex="1" 
        AllowPaging="false" DataKeyNames="ProductID" Width="100%" GridLines="Both" CellPadding="3" 
        AllowSorting="True" BackColor="White" onsorting="grdViewProducts_Sorting">
        <Columns>
            Add all the columns
        </Columns>
    </asp:GridView>
    <div id="divChildGrid">
    </div>
</div>
<input id="hiddenInitialNoOfPageLoad" type="hidden" value="0" runat="server" />
<input id="hiddenTotalRecords" type="hidden" value="0" runat="server" />
<input id="hiddenPageRecordCount" type="hidden" value="0" runat="server" />
<input id="hiddenSortExpression" type="hidden" value="0" runat="server" />
The C# Codebehind (ProcessMessageSorting.aspx.cs)
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        hiddenInitialNoOfPageLoad.Value = "2";
        hiddenPageRecordCount.Value = ConfigurationManager.AppSettings["PageRecordCount"].ToString();
        hiddenSortExpression.Value = "ProductName,Ascending";
        BindGrid();
    }
}
private void BindGrid()
{
    // Defining int variable to get the Total Record Count from Data layer
    int totalRecordCount = 0;

    // Get the SortByExpression and SortType from View State (by default, that will be updated in script)
    string strSortExpression = hiddenSortExpression.Value.Split(",".ToCharArray())[0];
    SortType sortType = (SortType)Enum.Parse(typeof(SortType), hiddenSortExpression.Value.Split(",".ToCharArray())[1], true);

    // Getting how many records required to show in the Grid per page
    int intPageRecordCount = Convert.ToInt32(hiddenPageRecordCount.Value) * 2; // I am fetching 3 pages at first time

    ProductDAO objProductDAO = new ProductDAO();

    IList<ProductView> ProductViewList = objProductDAO.GetProducts(1, intPageRecordCount, strSortExpression, sortType, out totalRecordCount); // Getting First three pages
    //Adding one empty row for just to show the grid
    if (ProductViewList.Count == 0)
        ProductViewList.Add(new ProductView());

    grdViewProducts.DataSource = ProductViewList;
    grdViewProducts.DataBind();

    // Assign the Total Record count to 
    hiddenTotalRecords.Value = totalRecordCount.ToString();

    // Try to find the sorted column
    for (int intRowIndex = 0; intRowIndex < grdViewProducts.Columns.Count; intRowIndex++)
    {
        if (strSortExpression == grdViewProducts.Columns[intRowIndex].SortExpression)
            ((LinkButton)grdViewProducts.HeaderRow.Cells[intRowIndex].Controls[0])
            .CssClass = (sortType == SortType.Ascending ? "sortup" : "sortdown");
    }
}
protected void grdViewProducts_Sorting(object sender, GridViewSortEventArgs e)
{
    string strSortExpression = hiddenSortExpression.Value.Split(",".ToCharArray())[0];
    SortType sortType = (SortType)Enum.Parse(typeof(SortType), hiddenSortExpression.Value.Split(",".ToCharArray())[1], true);

    if (strSortExpression == e.SortExpression)
        sortType = sortType == SortType.Ascending ? SortType.Descending : SortType.Ascending;
    else
    {
        strSortExpression = e.SortExpression;
        sortType = SortType.Ascending;
    }
    hiddenSortExpression.Value = e.SortExpression + "," + sortType.ToString();

    BindGrid();
}
The Javascript
function GetChildGrid(pageId) {

    // Get the Div
    var childGridDiv = document.getElementById("divChildGrid");

    if (childGridDiv) {
        // If the Child Grid is not fetched, then go and fetch it.
        var varTotalRecords = document.getElementById('<%= hiddenTotalRecords.ClientID %>').value;
        var varPageRecordCount = document.getElementById('<%= hiddenPageRecordCount.ClientID %>').value;
        var varSortExpression = document.getElementById('<%= hiddenSortExpression.ClientID %>').value;

        if ((pageId > 0) && (parseInt(varTotalRecords) > (parseInt(varPageRecordCount) * (parseInt(pageId) - 1)))) {

            var url = 'RowsBuilder.aspx?PageId=' + pageId +
                        '&PageRecordsCount=' + varPageRecordCount +
                        '&SortExpression=' + varSortExpression;
            xmlHttp = createAjaxObject();
            if (xmlHttp) {
                xmlHttp.open('get', url, true);
                xmlHttp.onreadystatechange = function () {
                    HandleResponse(pageId);
                }
                varPageOnBehind = varStartAJAXPage;
                xmlHttp.send(null);
            }
        }
    }
}
The output of this code would be:

The vedio output

download the working copy of the source code in C# here and in VB here.

The next post talks about the third implementation.

1 Response to “Rendering GridView Rows when scrolling down using AJAX concept - Part 2”

  • Anonymous says:
    11 June 2013 at 10:54

    Could tell me How can I achieve this functionality using MySQL database. My email venkatesh.vm115@gmail.com

Post a Comment