在DetailsView错误中选择全部复选框按钮

注意:我已经更新了这个问题的代码,以使示例更加清晰,并利用下面的Karl Anderson提供的示例代码。 我也愿意接受其他方式来获得我需要完成的任务。

我正在创建一个包含多个复选框的表单,这些复选框可能会或可能不会用于每个请求。 我正在尝试在DetailsView网格中的这些复选框下面创建一个按钮,只有在需要检查它们时才会检查(而不是检查和取消选中的按钮)。 从下面的代码中可以看出,复选框周围有多个文本框/ BoundField,它们包含此表单的各种类型的信息。 没有“检查所有复选框”按钮的复杂性的表单在前端和写入数据库时​​没有任何问题。

使用我面临的当前障碍下面的代码不仅让按钮一次只检查所有复选框,而是在页面加载时超过此错误:

无法通过引用转换,装箱转换,取消装箱转换,换行转换或空类型转换将类型’System.Web.UI.WebControls.TableCell’转换为’System.Web.UI.WebControls.CheckBox’

从我对类似(但不是确切)错误的研究,我需要将复选框转换为其他forms。 我以前从未遇到过这种情况,而且我不仅仅是在寻找教育参考,而是指出如何解决转换部分,但准确和当前(在过去几年内)如何解决我可以解决更大的按钮问题,正确检查所有19个复选框。

我在这里做错了什么,这是获得我想要的结果的正确方法吗? 我不仅想学习如何解决这个问题,还要学习这一挑战背后的理论/逻辑,以便我能以正确的方式学习它。

aspx代码。

(Note some cosmetic code for the details view has been omitted)                                        <asp:ButtonField ButtonType="Button" CommandName="btnSelectAll" Text="Select/Check All Servers"        <asp:SqlDataSource ID="SqlDataSource1" ConnectionString="" runat="server" InsertCommand="INSERT INTO [test].[detailsview_test_form] ([Field_1], [Field_2], [Field_3], [Field_4], [Field_5], [Field_6], [Field_7], [Field_8], [Field_9], [Field_10], [Check_Box_1], [Check_Box_2], [Check_Box_3], [Check_Box_4], [Check_Box_5], [Check_Box_6], [Check_Box_7], [Check_Box_8], [Check_Box_9], [Check_Box_10], [Check_Box_11], [Check_Box_12], [Check_Box_13], [Check_Box_14], [Check_Box_15], [Check_Box_16], [Check_Box_17], [Check_Box_18], [Check_Box_19], [Field_11], [Field_12], [Field_13]) VALUES (@Field_1, @Field_2, @Field_3, @Field_4, @Field_5, @Field_6, @Field_7, @Field_8, @Field_9, @Field_10, @Check_Box_1, @Check_Box_2, @Check_Box_3, @Check_Box_4, @Check_Box_5, @Check_Box_6, @Check_Box_7, @Check_Box_8, @Check_Box_9, @Check_Box_10, @Check_Box_11, @Check_Box_12, @Check_Box_13, @Check_Box_14, @Check_Box_15, @Check_Box_16, @Check_Box_17, @Check_Box_18, @Check_Box_19, @Field_11, @Field_12, @Field_13) ">                                     

…..和cs代码:

 using System; using System.Configuration; using System.Collections; using System.Data; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class form2 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void DetailsView1_ItemCommand(Object sender, DetailsViewCommandEventArgs e) { foreach (Details if (e.CommandName == "btnSelectAll") { DetailsViewRow row = DetailsView1.Rows[9]; (row.Cells[10] as CheckBox).Checked = true; DetailsViewRow row1 = DetailsView1.Rows[10]; (row1.Cells[11] as CheckBox).Checked = true; DetailsViewRow row2 = DetailsView1.Rows[11]; (row.Cells[12] as CheckBox).Checked = true; DetailsViewRow row3 = DetailsView1.Rows[12]; (row.Cells[13] as CheckBox).Checked = true; DetailsViewRow row4 = DetailsView1.Rows[13]; (row.Cells[14] as CheckBox).Checked = true; DetailsViewRow row5 = DetailsView1.Rows[14]; (row.Cells[15] as CheckBox).Checked = true; DetailsViewRow row6 = DetailsView1.Rows[15]; (row.Cells[16] as CheckBox).Checked = true; DetailsViewRow row7 = DetailsView1.Rows[16]; (row.Cells[17] as CheckBox).Checked = true; DetailsViewRow row8 = DetailsView1.Rows[17]; (row.Cells[18] as CheckBox).Checked = true; DetailsViewRow row9 = DetailsView1.Rows[18]; (row.Cells[19] as CheckBox).Checked = true; DetailsViewRow row10 = DetailsView1.Rows[19]; (row.Cells[20] as CheckBox).Checked = true; DetailsViewRow row11 = DetailsView1.Rows[20]; (row.Cells[21] as CheckBox).Checked = true; DetailsViewRow row12 = DetailsView1.Rows[21]; (row.Cells[22] as CheckBox).Checked = true; DetailsViewRow row13 = DetailsView1.Rows[22]; (row.Cells[23] as CheckBox).Checked = true; DetailsViewRow row14 = DetailsView1.Rows[23]; (row.Cells[24] as CheckBox).Checked = true; DetailsViewRow row15 = DetailsView1.Rows[24]; (row.Cells[25] as CheckBox).Checked = true; DetailsViewRow row16 = DetailsView1.Rows[25]; (row.Cells[26] as CheckBox).Checked = true; DetailsViewRow row17 = DetailsView1.Rows[26]; (row.Cells[27] as CheckBox).Checked = true; DetailsViewRow row18 = DetailsView1.Rows[27]; (row.Cells[28] as CheckBox).Checked = true; DetailsViewRow row19 = DetailsView1.Rows[28]; (row.Cells[29] as CheckBox).Checked = true; } } } 

你通过引用转换,装箱转换,拆箱转换,包装转换或空类型转换得到”System.Web.UI.WebControls.CheckBox’的原因是因为你试图将一个Cell转换成一个CheckBox。

请注意,我在Rows Cell的ControlCollection中找到了CheckBox控件。

下面是经过测试的示例代码:

形成:

            

代码背后:

  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(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(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(row.Cells[i].Controls); if (tb != null) { table.Rows[0][j] = tb.Text; } CheckBox cb = FindControl(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(); } } 

这是未经测试的,但应该工作,所以试试这个:

 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... } } 

尝试使用客户端脚本作为

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

其中btnClass是按钮的类,chkBoxClass是复选框的公共类。

如果在row.Cells[0]类的代码中设置断点并查看Controls属性(在Quick Watch窗口或其他调试窗口之一),您应该能够找到相关的CheckBoxes并找出如何从每个细胞向下遍历它们。

但是 ,这应该是一个非常糟糕的主意。 您的代码现在与页面结构紧密耦合。 这对你来说很难保持向前发展,而在这个项目上工作的任何人都可能要花很长时间来解决这个问题。 这段代码需要被抛弃。

如果您需要在表单上包含这么多字段,请考虑将这些字段完全分离到单独的页面上,并实际在页面本身上单独创建字段。 您可能认为这会花费更多时间给用户,但老实说 – 这个表单有13个参数和19个CheckBoxes 。 这是一种复杂的forms,需要特别注意和关注。

最后,您(以及其他开发人员)在对此页面进行改进和修复错误时节省的时间将非常快速地回馈用户。

根据卡尔安德森的回答:

 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; } } } 

不确定这是否能解决所有问题,但需要将其拉入循环中,我相信Controls[0]会对复选框进行处理。

我会尝试:

 protected void DetailsView1_ItemCommand(Object sender, DetailsViewCommandEventArgs e) { if (e.CommandName == "btnSelectAll") { var controls = new Stack(); 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); } } } } 

即使在不同的控制类型上,循环步行槽子控件也可以工作。

好的,所以你需要做的就是更改这一行:

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

到这一行:

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

TableCell实际用于呈现UI的控件。 对于CheckBoxField ,集合中的第一个控件是CheckBox

现在,为了使这段代码更具可伸缩性,我可能会这样做:

 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; }