views:

491

answers:

4

I am trying to check all the checkboxes on a webform (aspx) page, which is inside a master page, depending on the ID of the checkbox. The checkboxes are created dynamically, so I only know the prefix for finding it. So, I need to find these checkboxes by iterating the controls on the page somehow. It's not working out. Any help would be appreciated ...

Here is the code behind where the checking should occur ...

    Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
    Dim oCheckbox As System.Web.UI.WebControls.CheckBox = Nothing
    Dim oControl As Control = Nothing
    For Each oControl In Me.Controls
        If oControl IsNot Nothing Then
            If TypeOf oControl Is System.Web.UI.WebControls.CheckBox Then
                oCheckbox = oControl
                If oCheckbox.Text.StartsWith("ClientCheckBox_") Then
                    oCheckbox.Checked = True
                End If
            End If
        End If
    Next
End Sub
+1  A: 

The Controls collection is not deep or recursive - it only contains the immediate child controls. You need to do this operation recursively if you can't be sure where the controls may end up, or if you are sure, make sure you are targeting the specific container which you know contains all your checkboxes.

To recursively search, try something like:

Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
    CheckCheckBoxes(Me)
End Sub

Protected Sub CheckCheckBoxes(ByVal ctrl as Control)
    For Each childCtrl in ctrl.Controls
        If TypeOf childCtrl Is CheckBox AndAlso childCtrl.Text.StartsWith("ClientCheckBox_") Then
            CType(childCtrl, CheckBox).Checked = True
        Else
            CheckCheckBoxes(childCtrl)
        End If
    Next
End Sub
Rex M
Do this operation recursively on what, the controls themselves?
hmcclungiii
@hmcclungii yes - recurse down the control tree by moving across and into each controls collection.
Rex M
A: 
Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
   CheckAll(Me, "ClientCheckBox_")
End Sub

Sub CheckAll(parent as Control, startsWith as String)
   Dim cb as CheckBox = TryCast(parent, CheckBox)
   If cb IsNot Nothing AndAlso cb.Text.StartsWith(startsWith) Then
      cb.Checked = True
   End If

   For Each c as Control in parent
      CheckAll(c, startsWith)
   Next
End Sub
Mark Brackett
+2  A: 

Here is a non-jQuery example of how to do this client side. Let me know if you need any more help putting this example into practice.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Untitled Page</title>
    <script type="text/javascript" src="jquery-1.3.2-vsdoc2.js"></script>


    <script type="text/javascript">

        function selectDeselect(button) {
         var checked = (button.value === 'Select All');
         var checkboxes = document.getElementsByName('myCheckBoxGroup');            
         for (var i = 0; i <  checkboxes.length; i++) {
          checkboxes[i].checked = checked;
         }

         button.value = (checked) ? 'Deselect All' : 'Select All';      
        }

    </script>

    <style type="text/css">

    </style>
</head>
<body>

    <input type="button" value="Select All" onclick="selectDeselect(this);" />

    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />
    <input type="checkbox" name="myCheckBoxGroup" />

</body>
</html>
ChaosPandion
+1  A: 

For situations where you need controls to communicate with one another between hierarchies of objects, you're better off using an observer pattern as follows (can be adapted as server-side or client-side code as needed):

Start with a simple class to represent your notifier:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI.WebControls;

public class CheckAllManager
{
    public static CheckAllManager Instance
    {
        get
        {
            if (HttpContext.Current.Session["CheckAllManager"] == null)
            {
                HttpContext.Current.Session["CheckAllManager"] = new CheckAllManager();
            }
            return (CheckAllManager)HttpContext.Current.Session["CheckAllManager"];
        }
    }

    private HashSet<CheckBox> checkboxes = new HashSet<CheckBox>();

    private CheckAllManager() { }

    public void Register(CheckBox checkbox)
    {
        checkboxes.Add(checkbox);
    }

    public void Unregister(CheckBox checkbox)
    {
        checkboxes.Remove(checkbox);
    }

    public void CheckAll(bool checkState)
    {
        foreach (CheckBox checkbox in checkboxes)
        {
            checkbox.Checked = checkState;
        }
    }
}

Obviously, you should adapt this class to your own needs, but its very straightforward:

  • Call CheckAllManager.Instance.Register(checkbox) on checkbox creation.
  • Call CheckAllManager.Instance.Unregister(checkbox) on checkbox disposal.
  • Call CheckAllManager.Instance.CheckAll(state) to set the state of all checkboxes registered to the class.

This technique works without relying on checkboxes to be named a particular way or recursing down each objects Controls collection.

Juliet
If you're using .NET 2.0, substitute a Dictionary<CheckBox, object> for the HashSet, replace the Add method with checkboxes.Add(checkbox, null), and iterate through checkboxes using the foreach (CheckBox checkbox in checkboxes.Keys).
Juliet