问题
Within a web form I am dynamically creating a series of chekboxes that are added to an asp:placeholder
//Generates the List of Entities that may be shared
protected void GenerateEntityList(string agencyId, string agencyName)
{
var selectedAgency = UserFactory.GetAgencyAndSharedDataById(Convert.ToInt64(agencyId));
entityContainer.Controls.Clear();
//builds the entity list based upon entities in DB
var currentEntities = UserFactory.GetEntityList();
//add checkboxes
entityContainer.Controls.Add(new LiteralControl("<input type='checkbox' id='selectAllCB' value='All'>Select All<br/><br/>"));
foreach (var item in currentEntities)
{
CheckBox entityCheckBox = new CheckBox();
int currentItem = item.EntityTypeId.GetValueOrDefault(0);
entityCheckBox.Text = item.EntityName.ToString();
entityCheckBox.CssClass = "am_Checkbox";
entityContainer.Controls.Add(entityCheckBox);
entityContainer.Controls.Add(new LiteralControl("<br/><br/>"));
//mark checkboxes as checked if currently stored in the database
if (selectedAgency.FirstOrDefault().SecurityDataShares != null && selectedAgency.FirstOrDefault().SecurityDataShares.Count > 0)
{
foreach (var ce in selectedAgency.FirstOrDefault().SecurityDataShares)
{
if (ce.EntityId == item.EntityId)
{
entityCheckBox.Checked = true;
}
}
}
}
Once created the user has the ability to make or remove selections. When clicking update I would like to return/collect the values from the checkboxes so that I may insert them back into the db.
//get the text value of every checkbox
protected void updateEnties()
{
string receivingAgency = ReceivingAgencyID;
long contributingAgency = QueryID;
List<string> cbValues = new List<string>();
foreach (CheckBox currentItem in entityContainer.Controls)
{
cbValues.Add(currentItem.Text);
}
}
However when I attempt to iterate over the collection I am not getting anything back which leads me to believe either I am calling the control incorrectly or it is being destroyed due to the postback. Instead of writing these elements to a place holder should I use another controls like a Listbox control?
Can someone please provide me with some guidance on how I can retrieving the checkbox values?
回答1:
There are two schools of thought; one, that you need to recreate the control hierarchy that was made for the initial view so that the page can restore the view state and form values into the control tree, or two, that you can go with a low tech solution and simply get the values from the form collection.
I personally, like option two, and it's relatively easy to deal with, and since it looks like you're already manually creating the HTML with LiteralControl
. Simply provide a name
attribute that is shared among your manually created input tags (example shown here for brevity, this is probably not what you will do):
entityContainer.Controls.Add(new LiteralControl("<input type='checkbox' name='mySharedName' />");
Then, to get the values it is as simple as this:
var selectedValues = Request.Form["mySharedName"];
// This is now a comma separated list of values that was checked
Then you dont have to worry about the control tree state.
回答2:
It sounds like you could make life much easier just using a CheckBoxList
instead, and binding your result set to it. That would actually nullify the need for any dynamic content.
<asp:CheckBoxList ID="CheckList1" runat="server" DataTextField="TextColumn" DataValueField="ValueColumn" ...>
If that's not an option, then you need to recreate the controls after each postback. There are a couple ways to do this.
The easy way
Check out the DynamicControlsPlaceHolder control. This is a useful little control that takes care of persisting dynamic content behind the scenes. I would suggest this option, as it takes all of the pain away from dynamically created content.
The manual way
Recreate the control(s) during OnInit
. Just make sure you assign the same ID to the controls so that ViewState can repopulate the selections:
protected override void OnInit(EventArgs e)
{
var chk = new CheckBox { ID = "chkBox1" };
PlaceHolder1.Controls.Add(chk);
base.OnInit(e);
}
After recreating the control after the postback, you should be able to access the values like this:
foreach (CheckBox chk in PlaceHolder1.Controls.OfType<CheckBox>())
{
if (chk.Checked)
{
}
}
回答3:
Thanks to all for your suggestions. Based upon how this was being implemented I credited Tejs with the answer as he sent me down the thought path for this solution. In this project I needed to use checkboxes vs. a checkbox list control due to how I was building the list and verifying checked elements. The challenge came in with how asp.net generates the checkbox control as well as it's limitation on allowing the insertion of attributes to the control (name, value etc)
So to capture the vales from the code generated checkboxes I did the following:
Within the aspx file I added an hidden input field and assigned a runat=server tag
<input id="cbEntityList" type="hidden" runat="server" value="" />
Tejs solution was similar to this but I didn't like the idea of adding a hidden field for each checkbox as that seems like a lot of elements in the page.
I then modifed the checkbox code generation piece to include as the Id a unique identifier from my object. ID gets rendered out in the html as the name attribute so this allows me to how have something I can retrieve with javascript /jQuery
So within the foreach statement where I would build the checkboxes I added the following line
entityCheckBox.ID = item.EntityId.ToString();
Finally I used jQuery to iterate the page for checkboxes and return a string array of only checked items.
This would populate back to the hidden filed a value such as (0,1,2,3,4) based upon what checkbox was selected.
$('#btnUpdateEntities').click(function (event) {
var fields;
$(':checkbox:checked').each(function () {
var txt = $("input[name='cbEntityList']");
fields = ($(':checkbox:checked').map(function () {
return this.name;
}).get().join(","));
$(txt).val(fields);
});
});
I could then access the array of values in my code behind as:
string voo = cbEntityList.Value;
Hope this helps any interested.
回答4:
This is the kind of thing for which you should put together an implementation using OO principles. In this case, you should probably build your own CheckBoxCollection (inheriting from the proper interfaces/class). It would simplify the code and make it more compartmentalized and extensible.
One of the implementation details is then handling the situation you describe: throw in a click-handler that adds to the viewstate/session/whatever and you should be able to see whatever your test harness/users have checked/unchecked at a glance.
Another quick point: you shouldn't use <br /> tags for layout anymore, especially if you're already using CSS. You can make sure that checkboxen are whatever display type you need (block, in this case?), then set that in the CSS class with which you've already decorated the control.
tl;dr: I don't have time to throw up an example in code, but the basic idea is that you should have a CheckBoxCollection() which (according to your preference) preserves its CheckBox()s' .Checked states from action to action.
来源:https://stackoverflow.com/questions/10179589/how-to-get-the-checkbox-value-from-a-dynamically-generated-checkbox-list-in-asp