Monday, February 2, 2009

Maintaining State of CheckBox while Paging in GridView

0 comments
The Logic
We are storing the primary keys of the checkboxes that are checked into a List where T = data type of the primary key. This is done at PageIndexChanging before we change the page index and re-bind the GridView. And at RowDataBound we are checking whether the DataKeyName(primary key) of each row is in the List. If present , we mark the CheckBox as checked.
Heres the sample code.

The ASPX

<asp:LinkButton ID="btnSelectAllPage" runat="server" 
            CommandName="SelectAllPage" 
            Text="Select All Pages"
            OnCommand="SelectDeselectAllPages" />|
<asp:LinkButton ID="btnDeselectAllPage" runat="server" 
            CommandName="DeselectAllPage" 
            Text="Deselect All Pages"
            OnCommand="SelectDeselectAllPages" />|
<asp:LinkButton ID="btnSelectAll" runat="server" 
            CommandName="SelectAll" 
            Text="Select Page"
            OnCommand="SelectDeselect" />|
<asp:LinkButton ID="btnDeselectAll" runat="server" 
            CommandName="DeselectAll" 
            Text="Deselect Page"
            OnCommand="SelectDeselect" />

<asp:GridView ID="gvProducts" runat="server" 
            AllowPaging="True" 
            AutoGenerateColumns="False"
            DataKeyNames="ProductID"
            OnPageIndexChanging="gvProducts_PageIndexChanging" 
            OnRowDataBound="gvProducts_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="Select">
            <ItemTemplate>
                <asp:CheckBox ID="chkSelect" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
    <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False"
    ReadOnly="True" SortExpression="ProductID" />
    <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdsProducts" runat="server"
                ConnectionString='<%$ ConnectionStrings:NorthwindConnectionString %>'
                SelectCommand="SELECT * FROM Products">
</asp:SqlDataSource>



The ASPX.CS

private List<int> ProductIDs
{
    get
    {
        if (this.ViewState["ProductIDs"] == null)
        {
            this.ViewState["ProductIDs"] = new List<int>();
        }
        return this.ViewState["ProductIDs"] as List<int>;
    }
}

protected void SelectDeselect(object sender, CommandEventArgs e)
{
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            chkSelect.Checked = e.CommandName.Equals("SelectAll");
        }
    }
}

protected void SelectDeselectAllPages(object sender, CommandEventArgs e)
{
    DataSourceSelectArguments dssa = new DataSourceSelectArguments();
    dssa.AddSupportedCapabilities(DataSourceCapabilities.RetrieveTotalRowCount);
    dssa.RetrieveTotalRowCount = true;
    DataView dv = (DataView)sdsProducts.Select(dssa);
    foreach (DataRow dr in dv.Table.Rows)
    {

        int productID = Convert.ToInt32(dr.ItemArray[0]);//ItemArray[0] cos ProductID is in the first column
        if (e.CommandName.Equals("SelectAllPage") && !this.ProductIDs.Contains(productID))
        {
            this.ProductIDs.Add(productID);
        }
        if (e.CommandName.Equals("DeselectAllPage") && this.ProductIDs.Contains(productID))
        {
            this.ProductIDs.Remove(productID);
        }
    }
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            chkSelect.Checked = e.CommandName.Equals("SelectAllPage");
        }
    }
}

protected void gvProducts_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            int productID = Convert.ToInt32(gvProducts.DataKeys[gvr.RowIndex]["ProductID"]);
            if (chkSelect.Checked && !this.ProductIDs.Contains(productID))
            {
                this.ProductIDs.Add(productID);
            }
            else if (!chkSelect.Checked && this.ProductIDs.Contains(productID))
            {
                this.ProductIDs.Remove(productID);
            }
        }
    }
}

protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
    GridViewRow gvr = e.Row;
    if (gvr.RowType == DataControlRowType.DataRow)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            int productID = Convert.ToInt32(gvProducts.DataKeys[gvr.RowIndex]["ProductID"]);
            chkSelect.Checked = this.ProductIDs.Contains(productID);
        }
    }
}

As an extra enhancement, we are also giving provision for selecting, deselecting both page and the whole rows in every page also here.

P.S: We are using Northwind Sample DataBase by Microsoft, so if you dont have it download it.

Courtesy: A wonderful post by Ed Bruck at forums.asp.net
Read more...

Sunday, February 1, 2009

Insert Custom Advertisement Row in GridView

3 comments
Inserting advertisements between,say every tenth row populated by a gridview


The ASPX

<asp:GridView ID="GridView1" runat="server"  
AutoGenerateColumns="False"  
Height="171px" 
DataSourceID="sdsProducts"
Width="189px" 
OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"/>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdsProducts" runat="server" 
ConnectionString='<%$ ConnectionStrings:NorthwindConnectionString %>'
SelectCommand="SELECT * FROM Products">
</asp:SqlDataSource>

The ASPX.CS
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.DataItem != null)
{
int intCurrentId = e.Row.RowIndex;
if ((intCurrentId + 1) % 10 == 0)
{
// Add a row before this record
Table tblGrid = (Table)this.GridView1.Controls[0];
// Get the rowindex of the current row
int intIndex = tblGrid.Rows.GetRowIndex(e.Row);
// Create a new row to hold our subheading
GridViewRow gvrSubHeading = new GridViewRow(intIndex, intIndex, DataControlRowType.Separator, DataControlRowState.Normal);
// Create a table cell for the row
TableCell cellHeader = new TableCell();
// Set the colspan of the cell to the width of the table
cellHeader.ColumnSpan = this.GridView1.Columns.Count;
// Set the text
cellHeader.Text = "Your Advertisement goes here";
// Add the cell to the row
gvrSubHeading.Cells.Add(cellHeader);
// Add the row to the table
tblGrid.Controls.AddAt(intIndex + 1, gvrSubHeading);
}
}

}

Thats all.

P.S: The DataBase used is Northwind

Courtesy : Samu Zhang - MSFT of http://forums.asp.net
The original VB version posted by Samu Zhang can be found here
Read more...