asp.net datalist select all checkboxes per category
asp.net, checkbox, datalist
Solution
- Use HiddenFields to store `CatID` and `DocID`
- Use ASP.NET CheckBoxes instead of HTML-Inputs for both
- Handle the Check-All Checkbox' `CheckedChanged` event:
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;
}
}
on 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") %>' />
You also need to `EnableViewState=true` on the DataList to maintain checkbox state and enable checking/unchecking.
Edit:
Because you have problems to get it running, here's a complete working sample page.
Here are the required controls on aspx(note f.e. `<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>
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();
}
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;
}
}
The `CheckAllChanged` remains unchanged.
This works as expected even if you select a single document-checkbox and select a category-checkbox afterwards which causes a postback.
Problem
I have a page where users can select different documents files in a datalist control. The documents are categorized based on categories using the on pre-render event handler. Documents are selected based on Checkbox controls (not Checkboxlist). So far so good. What I want to happen next is to put a 'Select All' checkbox beside each Category's name which should select only checkboxes under that category. Here is the datalist control: ``` <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> ``` and here is the OnPreRender code: ``` 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; } } } ``` I have looked for something which can work within my code but no luck. And I am too invested in this code to now try Checkboxlist control (not sure if that would help anyway). Any ideas? I thought I could use: http://www.dotnetcurry.com/ShowArticle.aspx?ID=77 code but not sure how I can make that work? If I can somehow make the select all checkbox tie to a tag and then look for all tag then may be the link's code would help. Thanks!