Fandango68
Fandango68

Reputation: 4868

How to keep a Gridview's height the same, regardless of row numbers?

I have a common Gridview that is dynamic and has paging features. The number of rows could be anything from 0 to 'n'. When it's ZERO, I simply display a Label in the <EmptyRow> section. That is working.

I want to know how I can keep the height of the gridview set at 800px, without it stretching out the pager line.

I've tried the Height tag on the PagerStyle tag, but it makes no difference.

            <asp:GridView ID="gvFTUNSENT" runat="server" 
                AutoGenerateColumns="False" CellPadding="4" ForeColor="Black" AllowSorting="True" CssClass="gvCSS" Height="800px"
                DataKeyNames="StudentID,StudentUnitID" DataSourceID="sdsFTUNSENT" 
                GridLines="Vertical" AllowPaging="True" BackColor="White" BorderColor="#DEDFDE" BorderStyle="None" BorderWidth="1px" >
                <RowStyle Wrap="true" Height="48px" />
                <PagerStyle Height="20px" />
                <Columns>

My Gridview always looks like this...

enter image description here

My CSS ...

table.gvCSS {
  margin-top: 2px;
  font: 12px Verdana;
}

table.gvCSS > tbody > tr {
  background-color: white;
}

table.gvCSS > tbody > tr:nth-of-type(odd) {
  background-color: #EEE;
}

table.gvCSS > tbody > tr:first-of-type {
  background-color: #5D7B9D;
  color: white;
}

table.gvCSS > tbody > tr.selected-row {
  background-color: lightgreen;
}

table.gvCSSsub > tbody > tr.selected-row {
  background-color: lightyellow;
}

table.gvCSS tr td {
  padding: 3px 6px;
}

I want the pager line to stay at 20px, and the Gridview to "pad out" the remainding rows (if any) with blanks or empty rows.

Is that possible?

The reason is that I want the table to fit inside a table structure that is of fixed size.

Thanks

Upvotes: 0

Views: 1303

Answers (2)

Fandango68
Fandango68

Reputation: 4868

I resolved it myself.

Using the power of ViewState to be precise.

First declare it..

if (!Page.IsPostBack)
{
    ViewState["DataSourceID"] = string.Empty;
}

Add an OnLoad method..

OnLoad="GridView_Load"

    protected void GridView_Load(object sender, EventArgs e)
    {
        GridView gv = (GridView)sender;

        DataSourceSelectArguments dss = new DataSourceSelectArguments();

        //get the datasource related to the gridview
        SqlDataSource sds = (SqlDataSource)pnlMAIN.FindControl(gv.DataSourceID.ToString());
        if (sds != null)
        {
            //load the data again but this time into a dataview object
            DataView dv = (DataView)sds.Select(DataSourceSelectArguments.Empty);
            if (dv != null)
            {
                //convert the dataview to a datatable so we can see the row(s)
                DataTable dt = (DataTable)dv.ToTable();
                if (dt != null)
                {
                    //padd with blank rows to make up a full gridview of PAGESIZE (default 10) rows per page
                    if (gv.Rows.Count < gv.PageSize)
                    {
                        //and this is necessary to not stuff up gridviews with data beyond PageSize rows. Otherwise we'll have to handle the paging in code!
                        if (dt.Rows.Count <= gv.PageSize)
                        {
                            //loop through any "gap rows" and add empty rows
                            for (int wsRowAdd = (gv.Rows.Count + 1); wsRowAdd <= gv.PageSize; wsRowAdd++)
                            {
                                DataRow dr = dt.NewRow();
                                dt.Rows.Add(dr);
                            }

                            //accept the new rows
                            dt.AcceptChanges();

                            //reload the datatable back to the gridview
                            gv.DataSource = dt;
                            if (gv.DataSourceID != string.Empty)
                                ViewState["DataSourceID"] = gv.DataSourceID;
                            gv.DataSourceID = null;
                            gv.DataBind();
                        }
                    }

                    //hide gridview and reveal "emptyrow" label if there is no data to display
                    GridViewRow gHDR = (GridViewRow)gv.HeaderRow;
                    CheckBox cbHDR = (CheckBox)gHDR.FindControl("cbHDR");
                    if (gvNoData(gv))
                    {
                        gv.Visible = false;
                        Label lblEmpty = new Label();
((Label)pnlMAIN.FindControl("lblEmptyRow")).Style.Add("display", "");
                    }
                }
            }
        }
    }

I've made a method to return true or false if the gridview has any "empty" rows...

//checks if a gridview has any actual rows of data (not just blank rows filled in by the Load below
protected bool gvNoData(GridView gv)
{
    int wsDataRow = 0;
    foreach (GridViewRow gvRow in gv.Rows)
        if (gvRow.RowType == DataControlRowType.DataRow)
        {
            Label lblStudentName = (Label)gvRow.FindControl("lblStudentName");
            if (lblStudentName != null)
                if (lblStudentName.Text.Length > 0)
                    wsDataRow += 1;
        }

    //if a count was generated then there are data rows, otherwise the rows are blank or nonexistant
    if (wsDataRow > 0) return false;
    else return true;
}

Now the paging has to be handled by code. Here's what I did. Note that after the page has changed, I check if it's the last page in the gridview, and apply logic to create "blank" rows of data so the gridview's HEIGHT has not changed.

protected void GridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    GridView gv = (GridView)sender;
    gv.PageIndex = e.NewPageIndex;
    gv.DataBind();
}

protected void GridView_PageIndexChanged(object sender, EventArgs e)
{
    //here we control gridviews that have more than 10 rows so we can paginate and fill in rows like
    //we did above in GridView_Load(). But it could not be done there because we're adding more rows
    //to a gridview that has not had it's paging reformatted! We're doing so here

    GridView gv = (GridView)sender;

    //padd with blank rows to make up a full gridview of PAGESIZE (default 10) rows per page
    DataSourceSelectArguments dss = new DataSourceSelectArguments();

    //get the datasource related to the gridview
    string wsDataSourceID = (gv.DataSourceID == string.Empty) ? ViewState["DataSourceID"].ToString() : gv.DataSourceID;
    SqlDataSource sds = (SqlDataSource)pnlMAIN.FindControl(wsDataSourceID);
    if (sds != null)
    {
        //load the data again but this time into a dataview object
        DataView dv = (DataView)sds.Select(DataSourceSelectArguments.Empty);
        if (dv != null)
        {
            //convert the dataview to a datatable so we can see the row(s)
            DataTable dt = (DataTable)dv.ToTable();
            if (dt != null)
            {
                //have we reached the LAST page?
                if ((gv.PageIndex + 1) == ((gv.PageCount == 0) ? Convert.ToInt16(ViewState[wsDataSourceID + "PageCount"].ToString()) : gv.PageCount))
                {
                    //determines actual number of rows on the last page
                    int lastPageRowCount = dt.Rows.Count % gv.PageSize;
                    if (lastPageRowCount < gv.PageSize)
                    {
                        //loop through any "gap rows" and add empty rows
                        for (int wsRowAdd = (lastPageRowCount + 1); wsRowAdd <= gv.PageSize; wsRowAdd++)
                        {
                            DataRow dr = dt.NewRow();
                            dt.Rows.Add(dr);
                        }

                        //accept the new rows
                        dt.AcceptChanges();
                    }
                }

                //reload the datatable back to the gridview (either with extra rows, or the original data to not stuff up the paging)
                gv.DataSource = dt;
                if (gv.DataSourceID != string.Empty)
                    ViewState["DataSourceID"] = gv.DataSourceID;
                gv.DataSourceID = null;
                gv.DataBind();
            }
        }
    }
}

Now the gotcha in all this, is that we lose the PageCount value in the gridview, so it has to be saved before it's lost. I don't know why this happens, but ASP must see that once you've generated methods to handle paging then it defaults the PageCount to 0.

So this is how I handle that... Note that I am actually trying to handle this across 4 GridViews, so hence why I need a unique ViewState per gridview...

protected void GridView_DataBound(object sender, EventArgs e)
{
    GridView gv = (GridView)sender;

    //keep this because handing the last page and filling in rows, for some reason the PageCount is 0! And when it is, the DataSourceID could be null!
    //There should be 4 ViewStates to keep the PageCount of each GridView:
    //  1.  ViewState["sdsFTUNSENTPageCount"]
    //  2.  ViewState["sdsFTRESENDPageCount"]
    //  3.  ViewState["sdsASBAUNSENTPageCount"]
    //  4.  ViewState["sdsASBARESENDPageCount"]
    //  
    //  Each one will keep a PageCount value so that we don't lose it by using PageCount alone. And this is required so that we can "padd out"
    //  EmptyRows in the gridview when it's on the last page, giving the spreadsheet that clean un-shrinking look

    if (gv.PageCount != 0)
        ViewState[((gv.DataSourceID == string.Empty) ? ViewState["DataSourceID"].ToString() : gv.DataSourceID) + "PageCount"] = gv.PageCount;
}

And finally, I need to keep updating the ViewState of the DataSourceID, so that it can be reloaded as shown above.

I handle that here...

    protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        GridView gv = (GridView)sender;

        //update SourceID into memory, if it exists
        if (gv.DataSourceID != string.Empty)
            ViewState["DateSourceID"] = gv.DataSourceID;
}

It's long winded, but using ViewState throughout the program I found it handy to handle "old" vs "new" values and states that I can call upon when I need to.

And so by forcing blank rows, I've kept the height of the gridview intact when paging to the LAST page and most likely there are less than the 10 rows I expected.

MS should have provided a Persistence="true" property to avoid having to do all of this. Maybe in later versions of VS this has come about, but in my case I am using VS2005 and ASP.net 2. boo hoo.

I hope this helps someone.

Upvotes: 0

Kevin Shah
Kevin Shah

Reputation: 1617

try to put panel and give height to that like below

<asp:Panel runat="server" ID="pnlGrid" Height="500px" ScrollBars="Auto">

        </asp:Panel>

Thanks.

Upvotes: 0

Related Questions