asp.net dynamic controls values - asp.net

I am trying to create a poll system that will ask the users for the number of options they would like to add from a dropdownlist.
Then when the user choose a number i would like to add text-boxes for those numbers and finally use asp.net to iterate through the text-boxes and add their values in the database.
Example:
User chooses to add 5 options.
I use Jquery to to append 5 inputs to the form.
User adds their values.
I iterate through the text-boxes and execute a void based on these
values.
i am able to do the first 3 steps but i am stuck on the 4th step. To solve it i tried to use a loop:
foreach (TextBox tb in form1.Controls)
{
Response.Write(tb.Text);
}
but that throws an error:
Unable to cast object of type 'System.Web.UI.LiteralControl' to type 'System.Web.UI.WebControls.TextBox'.
how can i iterate throw the text-boxes?
thanks

Any static content is represented by a LiteralControl, which is why you experience that. A real easy way is to use LINQ:
var ctls = form1.Controls.OfType<TextBox>();
foreach (var ctl in ctls) { .. )
Or check the type as you loop through the controls to make sure it's a textbox first:
foreach (Control tb in form1.Controls)
{
if (tb is TextBox)
Response.Write(((TextBox)tb).Text);
}

Brian's answer seems a solid one. Another option that comes to mind at first sight is:
Declare a function...
Declare a simple array or even a string in js
Iterate from client side your inputs
And for each iteration you should be saving the value in that array or concatenating the value.
The array then can be saved as a string in some asp hiddenfield in order to do your server-side stuff.
Best regards.

Related

Foreach loop and placeholders

I have a placeholder in my .aspx file
When i add controls to in in the .aspx.cs file i also add some literal controls in addition to some tableboxes and labels, as such
phOutputs.Controls.Add(new LiteralControl("<tr><td>"));
phOutputs.Controls.Add(lbl1);
phOutputs.Controls.Add(new LiteralControl("</td><td>"));
phOutputs.Controls.Add(tbx1);
phOutputs.Controls.Add(new LiteralControl("</td></tr>"));
Down the road i tried using a foreach loop as like this
foreach (TextBox tbxInput in phOutputs.Controls)
but i get cast exceptions on run time saying you cant convert LiteralControl to tablebox.
What would be a better way of doing this?
The error is because your collection contains not only textboxes.
OfType extension can be used for filtering.
foreach (TextBox tbxInput in phOutputs.Controls.OfType<TextBox>())
{
}
Also as alternative - you can make a cast to a base class WebControl (instead of TextBox) in your foreach, but it depends on what you want to do in this loop. For sure, if you need textbox specific properties - this variant won't do.
You should first check whether the control is of type TextBox or not and then cast it to Textbox accordingly
foreach (control crtl in phInputs.Controls)
{
if(crtl is TextBox )
{
TextBox txt = (TextBox )crtl;
}
}
If you're trying to just loop over textboxes, you can use Linq to select only the controls that are textboxes and then iterate over those instead:
foreach(TextBox tbxInput in phOutputs.Controls.Where(o => o is TextBox))
Voila; no InvalidCastException.

ASP Multiselect listbox separator

I have encountered a problem and I didn't manage to find any soultions yet. Let me simplify things a bit.
I have 2 forms, the first contains an ASP ListBox with multi select mode enabled. I submit the form and in the other form I use just for testing purposes this snippet of code:
protected void Page_Load(object sender, EventArgs e)
{
foreach (string formKey in Request.Form.AllKeys)
{
if (formKey != null)
{
if (formKey.Equals("ctl00$MainContent$ListBox1"))
Label1.Text = Request.Form[formKey];
}
}
}
The problems is that the values that come from the listbox (the values that i selected in the previous form) are separated by "," for ex. "test1,test2,test3". How can i change this separator to "$" for example? I need to change it because the actual values may contain "," and i don't manualy feed them to the listbox.
I can't use any other mode of transfering this values between the form because the entire application uses this model. The values that i get are then sent to a workflow where there will be manipulated and in the workflow i need to know where each listbox item starts and ends so it must be an unique separator.
Any help is apreciated! Thank you very much
Thank you MatteKarla but unfortunately this does not solve my problem. Yes, this is a good way of transfering the values from one form to another.
However i must use the method I described above with Request form keys because the listbox is one of many others "parameters" that are generated at runtime and have their values sent to a workflow method that takes this values. And i can't afford to change that in my application.
My problem is that coma (",") separator is used by default with a multiselect listbox.
I thought that there maybe is a method to change that separator from coma to another char because the coma can also be included in the value itself and this will create confusion.
As i said if i select three values test1, test2 and test3, the result with my method will be a string looking like "test1,test2,test3". However a "test1$test2$test3" would be much better.
But I'm affraid that changing this default separator is not possbile. I must think at a method to overcome this problem like replacing before feeding the listbox all the intended coma from the values with some other char not to create confusion. But this is not a great way of doing it.
On your first page/form (First.aspx.cs) create a public property with the listbox:
public ListBox PostedListBox { get { return ListBox1; } }
Set the postback-url for the button to Second.aspx
Second page in the aspx-file after the #Page-directive add:
<%# PreviousPageType VirtualPath="~/First.aspx" %>
Then in Form_Load on Second.aspx.cs you can extract the values:
if (PreviousPage != null)
{
ListBox postedListbox = PreviousPage.PostedListBox;
foreach (var index in postedListbox.GetSelectedIndices())
{
var itemText = postedListbox.Items[index].Text;
}
}
Or you could just try to locate the control by using:
if (PreviousPage != null)
{
var control = PreviousPage.FindControl("ListBox1") as ListBox;
}
Third Edit:
You could use GetValues:
Request.Form.GetValues("ctl00$MainContent$ListBox1");
returns a string array containing each of the selected items.

Request.Form "Collection is only readonly" when trying to set text box content

Saving the values in the Lists & works fine.
abc= (ABC)(Session["xml"]);
string ctrlStr = String.Empty;
foreach (string ctl in Page.Request.Form)
{
if (ctl.Contains("something"))
{
ctrlStr = ctl.ToString();
abc.student[0].marks[j].science.something.Value = Convert.ToDecimal(Request.Form[ctrlStr]);
}
Want to retrieve the values from the saved object when I click on edit button back on the respective dynamic textboxes....
foreach (string ctl in Page.Request.Form)
{
if (ctl.Contains("studentname"))
{
ctrlStr = ctl.ToString();
(Request.Form[ctrlStr]) = abc.student[0].marks[x].science.studentname.ToString();---Gives an error stating the collection is only readonly
}
}
Request.Form — like the Request object generally — is read-only, reflecting the fact that, by the time you are responding to a request, the request itself cannot be changed. ASP.NET uses the values from the form POST to create server controls on the Page, and these allow you to control the values of the input and other form elements that are written to the Response object.
In your case, the TextBox controls are being generated dynamically, so they are not automatically bound to form values — hence your problem. You will need to keep references to the controls when they are created (or find them afterwards using the FindControl() method) and set their Text property.
(original answer follows)
The Controls collection becomes read-only at a certain point in the construction of the page. You have to do manipulation before that point. I don't remember offhand when it is, but you're safe with OnLoad through OnPreRender.
Where is your code firing from?
Update: Okay, I see what you're trying to do. This will be easiest if you're dealing with server-side controls (that is, controls generated by ASP.NET. That would look like this in your aspx (or ascx):
<asp:TextBox runat="server" ID="studentname"/>
Then you could update the value like this:
abc = (ABC)(Session["xml"]);
studentname.Text = abc.student[0].marks[j].science.something.Value.ToString();
That will set the value of the studentname text box automatically without needing to search through all of the Request.Form items. (Assuming you set j somewhere... I don't know the context for that.)
I can't tell for sure from your code, but it looks like you may just have a "plan HTML" input, which would look more like this:
<input type="text" name="studentname"/>
In that case, there is no simple way to update the value from your page's code, so I'd start by making sure that you're using server-side controls.
You can set the Request.Form values with reflection:
Request.Form.GetType().BaseType.BaseType.GetField("_readOnly", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(Request.Form, false);
Request.Form["foo"] = "bar";
What you are trying to achieve?
The Form collection retrieves the values of form elements posted to the HTTP request body, with a form using the POST method. - http://msdn.microsoft.com/en-us/library/ms525985(v=vs.90).aspx

Converting a string into a CheckBox

I have a string which is ultimately the id of a CheckBox.
What I need to be able to do is to access the CheckBox's properties from the string
var myCheckBox:Object;
var myString:String;
myString = "checkbox_1"
myCheckBox = Object(myString); ?!?!
... and then I'd need to get to myCheckBox.selected, and myCheckBox.label etc
easier answer:
if(this.hasOwnProperty(myString) && this[myString] is CheckBox) {
myCheckBox = this[myString] as CheckBox
}
It's a bit of overcoding (since the as keyword will return a null if it's not a checkbox and you could better handle it that way with potentially less code), but that should do ya.
Best of luck.
If you know what DisplayObjectContainer (e.g. Sprite, MovieClip) the CheckBox is inside you can use getChildByName.
Unfortunately if you are using Flex containers (like Group) there is no function getElementByName(). There is getElementAt so you could write a loop that iterates over all of a Groups elements until it encounters one that matches the name you have.

ASP.NET Dynamic Data setting the default value of a Dropdown list

I have a dropdown list (FK) which I would like to set and display a default value based on a login userid. Can you please tell me how to do it? I only want to affect the dropdown filter that appear at the top above the Gridview.
Thanks
Nikos
If you only want this functionality in the DropDown list that appears in the Filter Criteria section, just modify the URL by adding the QueryString parameters you would like to filter by. The DynamicFilter will pick up the values from the QueryString and set the DropDown lists accordingly. (fyi. this is the same functionality that the ForeignKey.ascx FieldTemplate provides)
It would be nice if there was a better way to actually create this URL (instead of using string), but as of right now, any solution I provide is probably going to break in a subsequent version.
example (in page_load)
Response.Redirect("~/Employees/List.aspx?ReportsTo=1234");
Is this a universal change, or just for one foreign key relationship?
Assuming it is for just one foreign key relationship, you could create a new FieldTemplate, to be used just for that relationship. The New FieldTemplate would be a copy of the default "ForeignKey" FieldTemplate. In the New FieldTemplate modify the OnDataBinding (or Page_PreRender) event to set the "default value" of the DropDownList.
Then, to force the New FieldTemplate to be used for that relationship, you would need to use the System.ComponentModel.DataAnnotations.UIHint attribute on the member of your Entity Class that represents that foreign key relationship. (links below)
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.uihintattribute.uihint.aspx
or http://www.asp.net/learn/3.5-SP1/video-291.aspx (around 07:30 mins)
For a little help, you could take a look at the DynamicData Futures release on CodePlex. Specifically the "Populate Insert templates with values from filters" section. http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=14475
I have figured out a workaround, but am open to a more elegant solution.
I edited the FilterUserControl.ascx.cs by inserting the following line in the Page_Init after PopulateListControl(DropDownList1);
DropDownList1.SelectedIndex = DropDownList1.Items.IndexOf(DropDownList1.Items.FindByText("Bob")); // Username is hardcoded just for test
This seems to work but I would prefer using the custom Partial Entity Class with metadata to solve this if possible.
I have solved this in an application I am working on, in your insert view template code behind:
In ItemCreated event for the details view:
foreach (DetailsViewRow row in DetailsView1.Rows)
{
foreach (Control ctl in row.Controls)
foreach (Control c in ctl.Controls)
foreach (Control x in c.Controls)
{
if (x.ClientID.Contains("tblName"))
{
foreach (Control y in x.Controls)
{
if (y.ClientID.Contains("DropDownList"))
{
ddl = y as DropDownList;
ddl.SelectedValue = Convert.ToString(UserId);
ddl.Enabled = false;
}
}
}
}
}
With this code, when a user is logged in and they go to insert some entity (tblName) the drop down list (fk to userId) is already selected and disabled.

Resources