按类别选择所有复选框的ASP.NET数据列表

3

我有一个页面,用户可以通过数据列表控件选择不同的文档文件。使用“预呈现”事件处理程序,根据类别对文档进行分类。文档是基于复选框控件(而不是复选框列表)选择的。到目前为止都很好。接下来我想实现的是在每个类别名称旁边放置一个“全选”复选框,它应只选择该类别下的复选框。这是数据列表控件:

<asp:DataList ID="DataList1" runat="server" RepeatDirection="Vertical" OnPreRender="DataList1_PreRender" DataKeyField="docid" EnableViewState="false">
<ItemTemplate>
    <table cellpadding="0" cellspacing="0" id="tbl_data">
        <tr>
            <td>
                <asp:Label ID="lblHeader" runat="server" Font-Bold="True" Font-Underline="True"></asp:Label>
             <asp:Label runat="server" id="lbl_cb_all" visible="false">Select All <input runat="server" id="cb_selectall" type="checkbox" value='<%# Eval("catid") %>' /> </asp:Label>
            </td>
        </tr>

        <tr runat="server" id="tr_data">
            <td>
                <asp:Label ID="lbl_categoryname" runat="server" Text='<%# Eval("categoryname") %>' Visible="false" /> <!-- Hide this; only used in Code Behind -->
                 <input runat="server" id="cb_docid" type="checkbox" value='<%# Eval("docid") %>' />
                  <asp:Hyperlink ID="hpl_docfileencr" Text='<%# Eval("docfileencr") %>' NavigateUrl='<%# "~/PDFEncr/" + DataBinder.Eval(Container.DataItem, "docfileencr") %>' Target="_blank"  runat="server" />
                <br />
            </td>
        </tr>
    </table>
</ItemTemplate>

以下是OnPreRender代码:

protected void DataList1_PreRender(object sender, EventArgs e)
{
    string strTempLabelCategory = "";
    foreach (DataListItem item in DataList1.Items)
    {



        Label lbl_categoryname = item.FindControl("lbl_categoryname") as Label;


        if (strTempLabelCategory.ToUpper() != lbl_categoryname.Text.ToString().ToUpper())
        {
            strTempLabelCategory = lbl_categoryname.Text.ToString().ToUpper();
            Label lblHeader = item.FindControl("lblHeader") as Label;
            lblHeader.Text = strTempLabelCategory.ToUpper();

            Label lbltempdiv = item.FindControl("lbl_cb_all") as Label;
            lbltempdiv.Visible = true;
        }
    }
}

我一直在寻找适用于我的代码的东西,但没有成功。而且我已经在这段代码中投入了太多的精力,现在不敢尝试Checkboxlist控件(也不确定它是否有帮助)。 有什么想法吗?我认为我可以使用:http://www.dotnetcurry.com/ShowArticle.aspx?ID=77 的代码,但不确定如何使其工作?如果我能让全选复选框与一个标签绑定,然后查找所有的标签,那么链接的代码可能会有所帮助。 谢谢!

使用jQuery来检查datalist元素的子项复选框。当全选被选中时,它会触发jQuery通过id获取datalist元素,然后循环遍历输入类型为复选框的子项,并将其切换为选中状态。 - Brian
Brian,谢谢。但我的问题是要找出“按id查找datalist元素,然后循环遍历其子元素”... - IrfanClemson
我尝试让每个ItemTemplate包含一个带有tbl_data ID的表格,然后找到父tbl_data表格以深入tr_data行内部的复选框,但是tbl_data表格正在为每个项目呈现。 - IrfanClemson
是的,你想要避免那种情况。你是如何创建asp:datalist的?这将是你需要识别的内容,或者是否所有内容都在一个datalist中,只是按类别排序。如果是这样,首先要做的是按类别拆分它,以便每个类别都包含在某个标识元素中。 - Brian
Brian,我在我的帖子中放了相关的.aspx和.cs代码。为了按类别分组,我使用预呈现(pre-render)。甚至可以看到在.aspx中的“全选”复选框(Select All checkbox)也出现了。我希望我能够像选择所有复选框一样为包含复选框的tr元素分配id,但是.net不允许动态ID。谢谢! - IrfanClemson
仍然没有解决方案。我稍后会再来检查。谢谢。 - IrfanClemson
3个回答

3
  1. 使用 HiddenFields 存储 CatIDDocID
  2. 使用 ASP.NET 的 CheckBoxes 替代 HTML-Inputs 来实现两者。
  3. 处理 Check-All Checkbox 的 CheckedChanged 事件:
protected void CheckAllChanged(Object sender, EventArgs e)
{
    CheckBox checkAll = (CheckBox)sender;
    DataListItem item = (DataListItem)checkAll.NamingContainer;
    HiddenField HiddenCatID = (HiddenField)item.FindControl("HiddenCatID");
    var catCheckBoxes = DataList1.Items.Cast<DataListItem>()
        .Where(li => ((HiddenField)li.FindControl("HiddenCatID")).Value == HiddenCatID.Value)
        .Select(li => li.FindControl("cb_docid"));
    foreach (CheckBox docCheckBox in catCheckBoxes)
    {
        docCheckBox.Checked = checkAll.Checked;
    }
}

在aspx页面中:
<asp:CheckBox runat="server" OnCheckedChanged="CheckAllChanged" AutoPostBack="true"  id="cb_selectall" />
<asp:HiddenField ID="HiddenCatID" runat="server" Value='<%# Eval("CatID") %>' />
<asp:HiddenField ID="HiddenDocID" runat="server" Value='<%# Eval("DocID") %>' />

您还需要在DataList上设置EnableViewState=true以保持复选框状态并启用勾选/取消勾选。
编辑: 因为您在运行时遇到问题,这里提供一个完整的工作示例页面。
以下是aspx上所需的控件(例如:<tr runat="server" id="tr_category">):
<ItemTemplate>
    <table cellpadding="0" cellspacing="0" id="tbl_data">
        <tr runat="server" id="tr_category">
            <td>
                <asp:Label ID="lblHeader" runat="server" Font-Bold="True" Text='<%# Eval("categoryname") %>' Font-Underline="True"></asp:Label>
                <asp:Label runat="server" ID="lbl_cb_all">Select All
                <asp:CheckBox runat="server"  OnCheckedChanged="CheckAllChanged" AutoPostBack="true"  id="cb_selectall" />
                </asp:Label>
            </td>
        </tr>
        <tr runat="server" id="tr_data">
            <td>
                <asp:HiddenField ID="HiddenCatID" runat="server" Value='<%# Eval("CatID") %>' />
                <asp:CheckBox runat="server" id="cb_docid" />
                <asp:HyperLink ID="hpl_docfileencr" Text='<%# Eval("docfileencr") %>' NavigateUrl='<%# "~/PDFEncr/" + DataBinder.Eval(Container.DataItem, "docfileencr") %>'
                    Target="_blank" runat="server" />
                <br />
            </td>
        </tr>
    </table>
</ItemTemplate>
  1. Ensure that the DataList is databound only if(!IsPostback), otherwise the checkbox selection will not be maintained:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack) BindDataList();
    }
    
  2. I'm using ItemDataBound instead of PreRender which is important for the ViewState to be reloaded correctly. I've also simplified all:

    protected void DataList1_ItemDataBound(Object sender, DataListItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType==ListItemType.AlternatingItem)
        {
            var row  = (DataRowView)e.Item.DataItem;
            var view = row.DataView;
            var lastRow = e.Item.ItemIndex == 0 ? null : view[e.Item.ItemIndex-1];
            var tr_category = (System.Web.UI.HtmlControls.HtmlTableRow)e.Item.FindControl("tr_category");
            var sameCategory = lastRow != null && (int)row["catid"] == (int)lastRow["catid"];
            tr_category.Visible = !sameCategory;
        }
    }
    
  3. The CheckAllChanged remains unchanged.

即使您先选择单个文件复选框,然后选择类别复选框(导致页面刷新),此功能仍能按预期工作。

Tim:你的编码已经生效了。稍后我会发布更新。仍需要弄清楚“取消选中”以删除所有复选框,以及将数据库处理改为使用asp:checkbox而不是之前的html checkbox。非常感谢! - IrfanClemson
<asp:CheckBox runat="server" OnCheckedChanged="CheckAllChanged" AutoPostBack="true" id="cb_selectall" /> 如果我取消勾选cb_selectall,则不会导致相应类别的复选框取消勾选。 - IrfanClemson
我相当确定这是由于您在DataList上的“EnableViewState=false”引起的。 - Tim Schmelter
我认为我已经将docid的hiddenfield合并了。需要超越它。 - IrfanClemson
HiddenField docid = li.FindControl("HiddenDocID") as HiddenField; string dbcmd = @"Insert Into [order_details] (orderid,docid) Values (" + orderid + "," + docid.Value.ToString() + ")"; - IrfanClemson
显示剩余10条评论

0

我认为通过对Tim的代码进行轻微修改,我已经使其正常工作。几点说明:因为否则“全选”触发器无法保持框被选中,所以我不得不禁用DataList的ViewState。我不明白为什么。此外,在page_load事件中没有ispostback检查,而datalist在每次加载时都会绑定。我不确定这是否是“最优”的方式。我还使用了两组Asp:RadioButtons:CheckAll和CheckNone,而不是复选框。无论如何,以下是相关的代码:

<asp:DataList ID="DataList1" runat="server" RepeatDirection="Vertical" DataKeyField="docid"
                EnableViewState="false" OnItemDataBound="DataList1_ItemDataBound">
                <ItemTemplate>
                    <table cellpadding="0" cellspacing="0" id="tbl_data">
                        <tr runat="server" id="tr_category">
                            <td>
                                <asp:Label ID="lblHeader" runat="server" Font-Bold="True" Text='<%# Eval("categoryname") %>'
                                    Font-Underline="True"></asp:Label>
                                <asp:Label runat="server" ID="lbl_cb_all">Select: All
                                    <asp:RadioButton runat="server" OnCheckedChanged="CheckAllChanged" AutoPostBack="true"
                                        ID="rb_selectall" GroupName="selectallnone" />
                                    | None
                                    <asp:RadioButton runat="server" OnCheckedChanged="CheckAllChangedNone" AutoPostBack="true"
                                        ID="rb_selectnone" GroupName="selectallnone" />
                                    <asp:HiddenField ID="HiddenCatID" runat="server" Value='<%# Eval("CatID") %>' />
                                    <asp:HiddenField ID="HiddenDocID" runat="server" Value='<%# Eval("docid") %>' />
                                </asp:Label>
                            </td>
                        </tr>
                        <tr runat="server" id="tr_data">
                            <td>
                                <asp:CheckBox runat="server" ID="cb_docid" Value='<%# Eval("docid") %>' />
                                <asp:HyperLink ID="hpl_docfileencr" Text='<%# Eval("docfileencr") %>' NavigateUrl='<%# "~/PDFEncr/" + DataBinder.Eval(Container.DataItem, "docfileencr") %>'
                                    Target="_blank" runat="server" />
                                <br />
                            </td>
                        </tr>
                    </table>
                </ItemTemplate>
            </asp:DataList>

 protected void DataList1_ItemDataBound(Object sender, DataListItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        var row = (DataRowView)e.Item.DataItem;
        var view = row.DataView;
        var lastRow = e.Item.ItemIndex == 0 ? null : view[e.Item.ItemIndex - 1];
        var tr_category = (System.Web.UI.HtmlControls.HtmlTableRow)e.Item.FindControl("tr_category");
        var sameCategory = lastRow != null && (int)row["catid"] == (int)lastRow["catid"];
        tr_category.Visible = !sameCategory;
    }
}

protected void CheckAllChanged(Object sender, EventArgs e)
{
    RadioButton checkAll = (RadioButton)sender;
    DataListItem item = (DataListItem)checkAll.NamingContainer;
    HiddenField HiddenCatID = (HiddenField)item.FindControl("HiddenCatID");

    var catCheckBoxes = DataList1.Items.Cast<DataListItem>()
        .Where(li => ((HiddenField)li.FindControl("HiddenCatID")).Value == HiddenCatID.Value)
        .Select(li => li.FindControl("cb_docid"))
        .ToList();
    foreach (CheckBox docCheckBox in catCheckBoxes)
    {
       // docCheckBox.Checked = checkAll.Checked;
        docCheckBox.Checked = true;
    }
 }

protected void CheckAllChangedNone(Object sender, EventArgs e)
{
    RadioButton checkAll = (RadioButton)sender;
    DataListItem item = (DataListItem)checkAll.NamingContainer;
    HiddenField HiddenCatID = (HiddenField)item.FindControl("HiddenCatID");

    var catCheckBoxes = DataList1.Items.Cast<DataListItem>()
        .Where(li => ((HiddenField)li.FindControl("HiddenCatID")).Value == HiddenCatID.Value)
        .Select(li => li.FindControl("cb_docid"))
        .ToList();

    foreach (CheckBox docCheckBox in catCheckBoxes)
    {
        docCheckBox.Checked = false;
    }


}

//订单按钮的部分代码如下;请注意HiddenField的使用

 CheckBox cb = li.FindControl("cb_docid") as CheckBox;

        if (cb != null)
        {
            if (cb.Checked)
            {
                HiddenField docid = li.FindControl("HiddenDocID") as HiddenField;
                string dbcmd = @"Insert Into [order_details] (orderid,docid) Values (" + orderid + "," + docid.Value.ToString() + ")";

0
 protected void chkAllN_CheckedChanged(object sender, EventArgs e)
    {
        lblSelectedRecord.InnerText = "0";
        /*this Foreach Loop performing for find gridview*/
        foreach (DataListItem dst in dstMulEmpSalInsert.Items)
        {
            GridView grd = (GridView)dst.FindControl("grdMulEmpSalInsert");
            CheckBox chk_All = (CheckBox)grd.HeaderRow.FindControl("chkAllN");

            if (chk_All.Checked == true)
            {
                /*this Foreach Loop performing for find gridview Controls*/
                foreach (GridViewRow gvr in grd.Rows)
                {
                    CheckBox chk_One = (CheckBox)gvr.FindControl("ChkSendOne");
                    

                    chk_One.Checked = true;
                    txt_Salary.ReadOnly = false;
                    lblSelectedRecord.InnerText = (Convert.ToInt32(lblSelectedRecord.InnerText) + 1).ToString();
                }
               

            }
            else
            {
                /*this Foreach Loop performing for find gridview Controls*/
                foreach (GridViewRow gvr in grd.Rows)
                {
                    CheckBox chk_One = (CheckBox)gvr.FindControl("ChkSendOne");
                    

                    chk_One.Checked = false;
                    

                }
                
            }
        }
        

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接