Select All checkboxes button in DetailsView errors

萝らか妹 提交于 2019-12-05 18:08:41

The reason you are getting "'System.Web.UI.WebControls.CheckBox' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion" is because you are trying to cast a Cell into a CheckBox.

Please note that I find the CheckBox control inside the Rows Cell's ControlCollection.

Below is tested sample code that works:

Form:

    <asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" OnItemCommand="DetailsView1_ItemCommand">
<AlternatingRowStyle BackColor="White" />
<Fields>
    <asp:ButtonField ButtonType="Button" CommandName="btnSelectAll" Text="Select/Check All Servers" />
    <asp:ButtonField ButtonType="Button" CommandName="btnEdit" Text="Edit" />
    <asp:ButtonField ButtonType="Button" CommandName="btnCancel" Text="Cancel" />
    <asp:ButtonField ButtonType="Button" CommandName="btnSave" Text="Save" />
    <asp:CommandField ButtonType="Button" NewText="CreateRecord" ShowInsertButton="True" />
</Fields>
</asp:DetailsView>

Code Behind:

    DataTable m_table = null;

    public DataTable table
    {
        get
        {
            if (ViewState["m_table"] != null)
                return (DataTable)ViewState["m_table"];
            else
                return null;
        }
        set
        {
            ViewState["m_table"] = value;
        }
    }


    public static T FindControl<T>(ControlCollection controls)
    {
        for (int i = 0; i < controls.Count; i++)
        {
            if (controls[i] is T)
                return (T)(object)controls[i];
        }

            return default(T);
    }


    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            table = new DataTable();

            DataColumn col1 = new DataColumn("Field_1");
            DataColumn col11 = new DataColumn("Check_Box_1");
            DataColumn col12 = new DataColumn("Check_Box_2");
            DataColumn col13 = new DataColumn("Check_Box_3");

            col1.DataType = System.Type.GetType("System.String");
            col11.DataType = System.Type.GetType("System.Boolean");
            col12.DataType = System.Type.GetType("System.Boolean");
            col13.DataType = System.Type.GetType("System.Boolean");

            table.Columns.Add(col1);
            table.Columns.Add(col11);
            table.Columns.Add(col12);
            table.Columns.Add(col13);

            DataRow row = table.NewRow();
            row[col1] = "1";
            row[col11] = false;
            row[col12] = false;
            row[col13] = false;

            table.Rows.Add(row);

            DetailsView1.DataSource = table;
            DetailsView1.DataBind();
        }

    }

    protected void DetailsView1_ItemCommand(Object sender, DetailsViewCommandEventArgs e)
    {
        if (e.CommandName == "btnSelectAll")
        {
            foreach (DetailsViewRow row in DetailsView1.Rows)
            {
                for (int i = 0; i < row.Cells.Count; i++)
                {
                    CheckBox cb = FindControl<CheckBox>(row.Cells[i].Controls);
                    if (cb != null)
                    {
                        cb.Checked = true;
                    }                        
                }                    
            }
        }
        if (e.CommandName == "btnSave")
        {
            int j = 0;
            foreach (DetailsViewRow row in DetailsView1.Rows)
            {
                for (int i = 0; i < row.Cells.Count; i++)
                {
                    TextBox tb = FindControl<TextBox>(row.Cells[i].Controls);
                    if (tb != null)
                    {
                        table.Rows[0][j] = tb.Text;
                    }

                    CheckBox cb = FindControl<CheckBox>(row.Cells[i].Controls);
                    if (cb != null)
                    {
                        table.Rows[0][j] = cb.Checked;
                    }
                }
                j++;
            }

            DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
            DetailsView1.DataSource = table;
            DetailsView1.DataBind();
        }
        if (e.CommandName == "btnEdit")
        {
            DetailsView1.ChangeMode(DetailsViewMode.Edit);
            DetailsView1.DataSource = table;
            DetailsView1.DataBind();
        }
        if (e.CommandName == "btnCancel")
        {
            DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
            DetailsView1.DataSource = table;
            DetailsView1.DataBind();
        }
    }

This is untested, but should work so try this:

protected void DetailsView1_ItemCommand(Object sender, DetailsViewCommandEventArgs e)
{
    // Use the CommandName property to determine which button
    // was clicked. 
    if (e.CommandName == "btnSelectAll")
    {
        // You may need to tweak this as I almost never use DetailsView, but the concept should work
        // Check the Apples checkbox
        // Apples is the first row (index 0) and second cell (index 1)
        DetailsViewRow row = DetailsView1.Rows[0];
        (row.Cells[1] as CheckBox).Checked = true;

        // Check the Oranges checkbox
        // Apples is the second row (index 1) and second cell (index 1)
        DetailsViewRow row = DetailsView1.Rows[1];
        (row.Cells[1] as CheckBox).Checked = true;

        // Keep moving through the rows...
    }

}

try using client side script as

$(".btnClass").click(function(){
$(".chkBoxClass").attr("checked", "checked");
});

where btnClass is the class for the button and chkBoxClass is the common class for the checkboxes.

If you set a breakpoint at code like row.Cells[0] and look at the Controls property (either in a Quick Watch window or one of the other debugging windows), you should be able to find your relevant CheckBoxes and figure out how to traverse down to them from each cell.

HOWEVER, this should strike you as a really bad idea. Your code is, right now, tightly coupled to the structure of the page. This is going to be very difficult for you to maintain going forward, and anyone else who works on this project is probably going to spend a very long time trying to figure this out. This code needs to be thrown out.

If you need to have this many fields on a form, consider separating these fields onto a separate page entirely, and actually create the fields separately on the page itself. You may be thinking that this will take more time for users, but honestly -- this form has 13 parameters and 19 CheckBoxes. That is a complicated form that requires some special care and attention.

Finally, the time you (and other developers) save while making improvements to this page and fixing bugs will pay the users back very quickly.

Based on Karl Anderson's answer:

protected void DetailsView1_ItemCommand(Object sender, DetailsViewCommandEventArgs e)
{
    if (e.CommandName == "btnSelectAll")
    {
        foreach (DetailsViewRow row in DetailsView1.Rows)
        {
            (row.Cells[1].Controls[0] as CheckBox).Checked = true;
        }
    }

}

Not sure if this fixes everything, but it needs to be pulled into a loop, and I believe Controls[0] will give a handle on the checkbox.

I would try:

protected void DetailsView1_ItemCommand(Object sender, DetailsViewCommandEventArgs e) {
  if (e.CommandName == "btnSelectAll") {
    var controls = new Stack<Control>();
    controls.Push(DetailsView1);
    while (controls.Count > 0) {
      var control = controls.Pop();
      var checkbox = control as CheckBox;
      if (checkbox != null) {
        checkbox.Checked = true;
      }
      foreach (Control childControl in control.Controls) {
        controls.Push(childControl);
      }
    }
  }
}

Recurrent walk trough child controls work even on different control types.

Okay, so all you need to do to access the check box is change this line:

(row.Cells[10] as CheckBox).Checked = true;

to this line:

(row.Cells[10].Controls[0] as CheckBox).Checked = true;

The TableCell holds a collection of controls that are actually used to render the UI. In the case of the CheckBoxField the first control in the collection is the CheckBox.

Now, to make this code a little more scalable, I might do this:

if (e.CommandName == "btnSelectAll")
{
    for (int i = 9; i < 29; i++)
    {
        DetailsViewRow row = DetailsView1.Rows[i];
        (row.Cells[i + 1].Controls[0] as CheckBox).Checked = true; 
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!