It seems like everywhere you read, everyone is talking about using ASP.NET MVC to create mobile Web applications. But what about programmers still working in Web Forms? We want our projects done using the latest techniques, we want to build mobile Web apps, and we want to use jQuery and Bootstrap, too.

Not to fear, Web Forms isn't dead and everything you can do in MVC, you can also do in Web Forms. This article will be the first of many where I'll show you tips and tricks for working with Web Forms, Bootstrap, and jQuery to build some great looking, mobile-aware Web applications. In fact, I'm creating a whole series of videos on how to use the latest techniques in Web Forms to build Web applications. This series of videos will be available in the summer of 2014 on www.pluralsight.com.

Select All or No Products

For this sample, you'll create a list of products using a GridView. Each row of the grid has a checkbox in the first column, as shown in Figure 1. Your users want to be able to perform an action on each selected row of the grid. Besides allowing the user to select each item one at a time, you also supply a check box above the grid that allows the user to select or deselect all of the rows at once. In addition, this check box is also a drop-down menu button (as you'll see in Figure 3) with the words “All” and “None” so the user can select from these menus as well.

If the user selects “All” from the menu, selects the check box, or checks an individual checkbox in the grid, the GridView displays two additional buttons (Figure 2) above the grid, namely Discontinue" and Delete. These buttons process the selected list of items in the grid and mark each selected product as discontinued or delete the row in the product table.

Figure 1: A list of products can be selected individually or collectively.
Figure 1: A list of products can be selected individually or collectively.
Figure 2: Once a product is selected, two additional buttons appear.
Figure 2: Once a product is selected, two additional buttons appear.
Figure 3: You can check all rows in the list or uncheck them all.
Figure 3: You can check all rows in the list or uncheck them all.

Add a CheckBox Column to GridView

For the GridView, you need to add a template column with a check box control. Set the ID attribute to “chkSelect” on the check box control as shown in Listing 1. Each check box needs to have the same ID pattern when it renders as HTML so that you can select all of them as a group using jQuery.

Listing 1: Add a Template Field to hold a check box field for each row of data

<asp:GridView ID="grdProducts"
              DataSourceID="odsProducts"
              AllowPaging="True"
              AutoGenerateColumns="false"
              PageSize="5"
              runat="server"
              CssClass="table table-striped">
    <Columns>
        <asp:TemplateField HeaderText="Select">
            <ItemTemplate>
                <asp:CheckBox ID="chkSelect" runat="server"
                              ProductId='<%# Eval("ProductId") %>'
                              Checked='<%# Eval("IsSelected") %>' />
            </ItemTemplate>
        </asp:TemplateField>
...
</asp:GridView>

When the GridView generates each row in the HTML table, it creates a “munged” ID made up of the parent control name, plus the ID you set, followed by an incrementing number. Below are example names of what the final HTML will look like:

  • MainContent_chkSelect_0
  • MainContent_grdProducts_chkSelect_1
  • MainContent_grdProducts_chkSelect_2

Create Check Box Button Group

Build the action button that has the check box and the drop-down using standard Bootstrap CSS classes. Start with a div tag to which you assign the class btn-group (Listing 2). The next div tag uses the btn classes to create a button look and also to contain the check box control.

Listing 2: Use the Bootstrap button group classes and drop-downs to create your action button.

<div class="btn-group">
    <div class="btn btn-primary btn-checkbox">
        <input type="checkbox"
               onclick="toggleDiscontinueDelete();"
               class="checkbox-inline"
               id="chkAction" />
    </div>
    <button class="btn btn-primary dropdown-toggle"
            data-toggle="dropdown">
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu">
        <li>
            <a href="#" onclick="selectAllProducts();">All</a>
        </li>
        <li>
            <a href="#" onclick="unselectAllProducts();">None</a>
        </li>
    </ul>
</div>

Below the check box element is a button element using the Bootstrap data-toggle attribute set to dropdown. For the drop down portion of this button, use an unordered list with each list item element containing an anchor tag for the All and None menus. Each of the anchor tags has its OnClick attribute set to call the appropriate JavaScript functions to select or deselect all items in the grid.

Each time the check box named chkAction is checked, you select all check boxes within the grid and make the Discontinue and Delete buttons visible. When the check box is unchecked, unselect all the check boxes in the grid and make the Discontinue and Delete buttons invisible. The toggleDiscontinueDelete() JavaScript function (Listing 3) is responsible for performing these actions.

Listing 3: A jQuery selector makes selecting and unselecting all check boxes in the grid very easy.

function toggleDiscontinueDelete() {
    // Check if 'Action' button is checked or not
    if ($("#chkAction").is(':checked')) {
        // Select all Products in Grid
        $("input[id*='chkSelect']").prop("checked", true);
        // Make discontinue and delete buttons visible
        makeButtonsVisible();
    }
    else {
        // Unselect all Products in grid
        $("input[id*='chkSelect']").prop("checked", false);
        // Make discontinue and delete buttons Invisible
        makeButtonsInvisible();
    }
}

The first line in the toggleDiscontinueDelete function is to check whether or not the chkAction check box is checked. You need to set the checked attribute to true for each of the chkSelect check boxes in the grid. You can use the selector “*=” to find all input elements that contain the ID chkSelect. Once you have selected that list, you call the prop() method passing in the name of the attribute to set and the value true or false to either check or uncheck the boxes.

Select all CheckBoxes in GridView

In Listing 4, you can also select or unselect all rows using the two drop-down menus All and None respectively. Each of these call their own functions: selectAllProducts and unselectAllProducts. Use the same jQuery selector to get a collection of check boxes in the grid. You then set the checked property to true or false for all of them. You also need to check or uncheck the chkAction button.

Listing 4: Use jQuery to select and unselect all rows in the grid.

function selectAllProducts() {
    // Uncheck the 'Action' button
    $("#chkAction").prop("checked", true);

    // Select all Products in Grid
    $("input[id*='chkSelect']").prop("checked", true);

    // Make discontinue and delete buttons visible
    makeButtonsVisible();
}

function unselectAllProducts() {
    // Uncheck the 'Action' button
    $("#chkAction").prop("checked", false);

    // Unselect all Products in grid
    $("input[id*='chkSelect']").prop("checked", false);

    // Make discontinue and delete buttons Invisible
    makeButtonsInvisible();
}

Make Buttons Visible and Invisible

The function makeButtonsVisible shown in the following code snippet makes the Discontinue and the Delete buttons visible. This function should be placed in <script> tags at the beginning of your Web page.

function makeButtonsVisible() {
    $("#discontinueButton").removeClass("invisible");
    $("#deleteButton").removeClass("invisible");
}

The code to make the buttons visible is the same, except you use the addClass method to add the “invisible” class to the anchor tags. This snippet makes the anchor tags invisible on the Web page

function makeButtonsInvisible() {
    $("#discontinueButton").addClass("invisible");
    $("#deleteButton").addClass("invisible");
}

Create the Discontinue and Delete Buttons

The Discontinue and Delete buttons are anchor elements styled using the Bootstrap btn styles and one additional style I created, called invisible. This invisible style definition, display: none; causes any element to be made invisible. Initially, you don't want these buttons to display, so this style takes care of that. Each of these buttons is marked as runat="server" because when the user clicks these buttons, you run code on the server to process the selected rows in the grid. The anchor elements also contain a span element and an <i> element that's used to display the glyph icons from the Bootstrap library. See Listing 5.

Listing 5: Create buttons using <a> tags and Bootstrap “btn” styles.

<a runat="server"
   id="discontinueButton"
   class="btn btn-success invisible"
   onserverclick="discontinueButton_ServerClick">
       <span id="spnDiscontinue" class="btn-label invisible">
           <i class="glyphicon glyphicon-minus"></i>
       </span>
   Discontinue</a>
<a runat="server" class="btn btn-danger invisible"
   id="deleteButton"
   onserverclick="deleteButton_ServerClick">
       <span id="spnDelete" class="btn-label invisible">
           <i class="glyphicon glyphicon-trash"></i>
       </span>
   Delete</a>

Discontinue, Delete, and Invisible are useful styles of buttons to add to your app.

Connect all Check Box Click Events

The last piece of client-side code hooks to the click event of all the check boxes in the table. If you have a single check box checked, the Discontinue and Delete buttons need to be visible to the user. If none of the check boxes are selected, the buttons need to be invisible. The code shown in Listing 6 is the function to connect to all of the click events. Note that you call the same functions you wrote earlier: makeButtonsVisible and makeButtonsInvisible.

Listing 6: Use jQuery to select all check boxes in the table and connect to their Click event procedures.

$(function () {
    // Get all checkboxes in grid
    // They all will contain 'chkSelect'
    var checkboxes = $("input[id*='chkSelect']");

    // Connect to click event.
    checkboxes.click(function () {
        // If any are checked, make Discontinue and Delete
        // buttons visible
        if (checkboxes.is(":checked")) {
            makeButtonsVisible();
        }
        else {
            makeButtonsInvisible();
        }
    });
})

Get Selected Products on the Server-Side

Now that you have the code to select all products, you need to get the list of checked rows on the server-side so you can either discontinue or delete the selected products. The method GetSelectedProducts shown in Listing 7 loops through the GridView collection of rows and builds a generic list of integers that represent the primary keys (ProductId) in the product table. The ProductId was an attribute added to the check box control in the GridView template column.

Listing 7: Loop through the list of rows in the GridView and locate those selected.

protected List<int> GetSelectedProducts()
{
    List<int> list = new List<int>();

    // Loop through all rows in the GridView
    foreach (GridViewRow row in grdProducts.Rows)
    {
        if (row.RowType == DataControlRowType.DataRow)
            {
                // Get the checkbox
                CheckBox chkRow = (row.Cells[0].
                  FindControl("chkSelect") as CheckBox);
                if (chkRow.Checked)
                {
                    // Get Product ID from checkbox attribute
                    list.Add(Convert.ToInt32(
                    chkRow.Attributes["ProductId"]));
                }
            }
        }

        return list;
}

As you loop through each row, first check to see whether the RowType is a DataRow and not a header or footer row type. If you are in a DataRow, grab the first cell in the table and find the check box control. If the check box control is checked, grab the ProductId attribute and add it to the collection of integers that will be returned from this method.

Discontinue or Delete Products

Once you have retrieved the collection of primary keys selected, loop through the list and either call a method to discontinue or delete the products. In the next code snippet, you pass the list of integers to a Discontinue method of a ProductManager class. Write the appropriate code in that method to loop through and discontinue each product in the list.

protected void discontinueButton_ServerClick(object sender,
EventArgs e)
{
    ProductManager mgr = new ProductManager();
    // Get list of products selected
    List<int> list = GetSelectedProducts();
    // Call method to discontinue list of Product IDs
    mgr.Discontinue(list);
}

Summary

In this article, you learned how to use Web Forms, JavaScript, jQuery and server-side code to select a set of records and do something with that set. On the client-side, you built a modern-looking interface using Bootstrap. You added some great functionality to allow selecting and unselecting a set of records and then passing that selection to the server-side for processing. None of this code was any different from MVC.

In the sample code, you can see that I disabled ViewState on this page, making the resulting HTML code not much (if any) larger than had I written this with MVC. So, yes, ASP.NET Web Forms can generate the same modern Web designs and mobile-aware applications as MVC.

NOTE: You can download the sample code for this article by visiting my website at http://www.pdsa.com/downloads. Select PDSA Articles, and then select Code Magazine � Action Buttons from the drop-down list.