Problem with dynamic table in ascx control - c#

I have the following table in an ascx user controll:
<tr runat="server" id="rowChangeSerNo">
<td colspan="2">
<table id="tblChangeSerNo" runat="server">
</table>
</td>
</tr>
<tr id="row" runat="server">
<td>
<asp:Button ID="btChangeSerNo" runat="server" Text="Update" OnClick="btChangeSerNo_onClick" />
</td>
</tr>
I create the tblChangeSerNo dynamically with text boxes prefilled with the current values in the db. The idea of the control is to allow the user to update the values of the DB with new values. The problem is that when the btChangeSerNo_onClick method is called:
The table is not rendered, since I do it on pre-render
Even if I rendered the table on Page_Load I could not access updated values of the user because they are lost.
How can I solve this problem?

The best practice way will be to use Grid control instead.
If you prefer to stick with your own code, follow those steps:
Store all the text boxes in global fields, e.g. public List<TextBox> m_tableTextboxes = new List<TextBox>(); and when creating add to that list.
Have the code creating the dynamic controls in the Page_Load but execute it only when not is PostBack: if (!Page.IsPostBack) { ... }
In the button click event, read the values from your global field.
Done something similar in the past, so the concept should work.

Related

How to create a limited number of pre-configured DropDownList and Textbox

I'm trying to create in a repeater a DropDownList and a TextBox for simulating a typical question list
My question is, how can I create 5 rows in my repeater with this dropdownlists and textboxes
Q: DropDownList1
A: TextBox1
Q: DropDownList2
A: TextBox2
Q: DropDownList3
A: TextBox3
Q: DropDownList4
A: TextBox4
Q: DropDownList5
A: TextBox5
Another day we could change the number of questions to 3, so my repeater should bind 3 Q-A
How can I do this dynamically.
I create the structure like this... but I don't know how to begin the Load event in order to render as I said before.
<asp:Repeater ID="repeater1" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:DropDownList ID="ddlQuestion" runat="server" />
</td>
</tr>
<tr>
<td>
<asp:TextBox ID="txtAnswer" runat="server" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Easiest way might be to encapsulate those low-order controls in a higher order control (namely an ASCX) and then add that to the placeholder in a loop. This way you get the benefit of being able to easily change the ASCX without repercussions on the outer looping code.
Edit: "adding" means creating the controls and then attaching them as children.

How do I create new controls inserted into newly generated HTML on runtime?

I am still rather new to ASP.NET, but I find myself stuck on a problem that shouldn't be too much of a problem..
Right now I have a page that holds this div:
<div id="EditSurveySetID" class="EditSurveySet" runat="server">
<div class="cell">
<div class="cell_title">Survey Set(s)</div>
<table id="surveySetTableData" runat="server" style="margin: 10px;">
<tbody>
<tr>
<td class="form_labelSurveySet" style="width: 330px;">
<input type="button" value="-"> Survey Set 1:
<input id="EditSurveySetTitle" runat="server" style="width: 200px;" value="Netherlands">
</td>
<td>
<asp:DropDownList ID="DDLSurveySetSurveys" runat="server">
</asp:DropDownList>
<asp:Button ID="addAdditionalDDLColumns" runat="server" Text="+" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
Which looks like this:
I want a user to press the + button (addAdditionalDDLColumns). Upon pressing that button, I want a new table row to appear with the same controls in it, so that on runtime, it would look like this at that point:
<div id="EditSurveySetID" class="EditSurveySet" runat="server">
<div class="cell">
<div class="cell_title">Survey Set(s)</div>
<table id="surveySetTableData" runat="server" style="margin: 10px;">
<tbody>
<tr>
<td class="form_labelSurveySet" style="width: 330px;">
<input type="button" value="-"> Survey Set 1:
<input id="EditSurveySetTitle" runat="server" style="width: 200px;" value="Netherlands">
</td>
<td>
<asp:DropDownList ID="DDLSurveySetSurveys" runat="server">
</asp:DropDownList>
<asp:Button ID="addAdditionalDDLColumns" runat="server" Text="+" />
</td>
</tr>
<tr>
<td class="form_labelSurveySet" style="width: 330px;">
<input type="button" value="-"> Survey Set 2:
<input id="Text1" runat="server" style="width: 200px;" value="Netherlands">
</td>
<td>
<asp:DropDownList ID="DropDownList1" runat="server">
</asp:DropDownList>
<asp:Button ID="Button1" runat="server" Text="+" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
Or in image:
So the way I see, some new HTML code is generated on the + button click event, along with some controls (dropdownlist, another + button with the same functionality(?), possibly a textfield instead of input field).
Questions that come to mind right now:
How do I generate the HTML code that would create a new table row
How do I control where this generated HTML code is added (in this case, it should be under the existing
[Vague/Abstract question] Ultimately a user could possibly have 1 to infinite 'survey sets'. If a user were to have created 4 survey sets, he would eventually press a save button or something alike. Upon pressing this button I would save the 4 selectedvalues of the 4 dropdownlists belonging to the 4 survey sets. How would I call each individual dropdownlist in order to get the data? What I'm actually asking, I think, is whether it's possible to assign an ID programmatically upon the auto generated dropdownlist creation of my previous two questions.
How do I do this? Any advise and tips are very welcome!!
You could use and UpdatePanel and dynamically add new asp controls in the code-behind.
This could be expensive however, because it means your application would be going back to the server every time the user clicks the "Add" button, however I'm not sure how you'd achieve this strictly on the client-side. But there is nothing stopping you creating new controls on the fly on the server-side using asp.net.
If you want to surround the new controls with custom HTML, you could use a PlaceHolder component and replace it with raw text (your HTML) during the callback.
I would suggest you use a GridView.
It provides an option to add rows. It provides a Rows collections, so you can get the data bound to each row.
Here are some examples to get you started.
Dynamically creating, adding and maintaining controls would involve some effort. You would need a PlaceHolder and have to add controls to that. You would have to assign unique ids to each one of them, and use those to retrive the values. This must be done on each PostBack.
Try this when you don't feel you are rather new to asp.net.
protected void Button1_Click(object sender, EventArgs e)
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell td = new HtmlTableCell();
Button btn=new Button();
btn.Text="gdfgd"; /* here u can create ur contol and add it in cell*/
td.Controls.Add(btn); /*add controls to colum*/
tr.Cells.Add(td); /*add column to row*/
surveySetTableData.Rows.Add(tr); /*ad row to table*/
}
instead of using this i would also recommend u to use gridview like nunespaqscal bcz dataretrival become very easy....in gridview

Reading dynamically generated HTML element value in codebehind in ASP.NET

I have an asp.net page where I have the below markup. Basically this markup is generated from codebehind by reading records from a table and looping through them. For each record in table, there will be a div block.
Basically this form is to read/show settings for a user. The settings entries are stored in a table.
<div id='divContainer' runat='server'>
<div id='div1' runat='server'>
<table>
<tr>
<th>Name</th>
<td><input type='text' id='txtName1' value='something' /></td>
</tr>
</table>
</div>
<div id='div2' runat='server'>
<table>
<tr>
<th>Domain name</th>
<td><input type='text' id='txtName2' value='something' /></td>
</tr>
</table>
</div>
<div id='div3' runat='server'>
<table>
<tr>
<th>URL</th>
<td><input type='text' id='txtName3' value='something' /></td>
</tr>
</table>
</div>
<div id='div4' runat='server'>
<table>
<tr>
<th>Some other value is enabled ?</th>
<td><input type='checkbox' id='chk4' /></td>
</tr>
</table>
</div>
</div>
The id's of each input element will be unique. Now in codebehind I want to read the values of each input element to save the changes user made. How can I read the elements here? Since the mark up is generated in codebehind as a string and appended the the INNER HTML of the external div, I can't read values like we do for a control which we drag and drop in the IDE.
If these are being sent back to the page in a standard HTTP POST then you can read the values in the Request.Form NameValueCollection.
Essentially, all of the server controls that become form elements get translated into standard HTML form elements just as you have there, albeit with more markup generated by .NET to help it identify them. Then it automatically maps their values back to the server controls for you on the postback, but the values themselves are still just in a standard HTTP POST, which you can access manually.
(This is also a common method used when posting a form from one ASP .NET application to another.)
If you want to grab your values for the generated controls you have to do 2 things.
Generate the input controls with a runat='server' tag for each control (otherwise they will not be included in the Request.Forms collection.) This is probably the step your missing.
<input type='text' id='txtName1' runat='server' value='something' />
Grab your values from the Request.Form collection on postback
string txtValue1 = Request.Form["txtName1"];
It really should be that easy. I tested this against your code using a DIV as the container and a simple javascript to inject the control string into the innerHTML. If your getting any issues you may have to debug and see if the dynamic control ID has changed due to inserting them into naming container or something.
So the brunt of the story is that when you dynamically add a control after Page_Init then POSTBACK values can not be inserted back into those controls.
CF: http://www.15seconds.com/issue/020102.htm and http://msdn.microsoft.com/en-us/library/ms178472.aspx
Some of the other answers here suggest "oh, add a runat=server to the control" but when you create it in the codebehind, and not in the Page_Init, then that makes ZERO difference.
Let me know if that's not how you're creating the controls or if that's not how you're using them and I'll revise this answer on more details. It really all boils down to how you're trying to access the values.
Generally, you'd place those input controls you're creating dynamically (in this case, a TextBox) inside something like a panel control (the container). Then after the user has posted their data, you'd loop that container panel.Controls collection and retrieve each TextBox text.
Be aware that some caveats apply when working with dynamically created controls because ASP is of stateless nature.
This page shows how to implement this:
Adding Dynamic Rows in ASP.Net GridView Control with TextBoxes
I didn't test it but I can suggest that:
Add your dynamic controls with runat="server" tag inside another controls with runat="server"(such as panel control). Then you can access them like this:
Textbox t = (Textbox)panel1.controls.findControl("dynamicControlId");

How do I acquire the value of a ASP label if it is nested? (client-side)

So there is a ASP checkboxlist that gets rendered to the table and in the code behind the checkboxes get bound with a label from a code table. I need to display a text box only if a certain checkbox is checked off.
<table id="chkSomeCheckbox">
<tbody>
<tr>
<td>
<input type="checkbox" id="chkSomeCheckbox_0">
<label for="chkSomeCheckbox_0">Acme</label>
</td>
<td>
<input type="checkbox" id="chkSomeCheckbox_1">
<label for="chkSomeCheckbox_1">Other</label>
</td>
</tr>
</tr>
</tbody>
</table>
The checkboxlist renders a table which the element retains the ID. I have tried to just get the value of the label when a checkbox is checked and then go from there to create my logic - but I can't seem to be able to grab the value of the label. I have tried the following different ways:
$("#<%chkSomeCheckbox.ClientID> input").next("label").val();
or
$("#<%chkSomeCheckbox.ClientID> input").next().val();
I am using the input selector because when I get this first part working, I will need to do some logic on it.
Any thoughts?
This is tagged as ASP.NET rather than ASP so I'm curious as to why you are not using ASP.NET controls. Also you have an extra </tr> tag in there.
You could do this:
<table id="chkSomeCheckbox">
<tr>
<td>
<asp:CheckBox ID="chkSomeCheckbox_0" runat="server"
Text="Acme" Checked="true" />
</td>
<td>
<asp:CheckBox ID="chkSomeCheckbox_1" runat="server"
Text="Other" Checked="false" />
</td>
</tr>
</table>
In the Page_Load event of the code behind you could then check the Checked property of the CheckBox and then decide to display the area that you held the Textbox in or just change the Visible property of the TextBox itself.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (chkSomeCheckbox_0.Checked)
{
txtSomeTextbox.Visible = true;
}
}
}
Tried this?
$("#<%= chkSomeCheckbox.ClientID %> input").next("label").val();
In your code sample the ASP.NET inline statement is not closed (and also the "=" sign is missing).
Note: This will only work in the aspx/ascx file, not in a external JavaScript file.
If you can grab a handle on the label that you want, you can probably call the .text() method to get the text of the label. As such, I don't think that labels have a "value"
For example, if you wanted to append a textbox after the label based on which one was checked you could do this:
$("#chkSomeCheckbox > input").change(function(){
$label = $(this).next();
if($(this).attr("selected") == true)
{
//get label text
foo = $label.text();
//append textbox after the label, etc
$label.append(textbox);
}
});A

How can I use the ScrollTo jQuery plugin to scroll to particular row in a repeater in ASP.NET?

I have a simple repeater that looks like:
<asp:Repeater runat="server" ID="rptOptions" OnItemDataBound="rptOptions_ItemDataBound">
<HeaderTemplate>
<thead>
<tr>
<td class="GridHeader">Account</td>
<td class="GridHeader">Margin</td>
<td class="GridHeader">Symbol</td>
<td class="GridHeader">Usymbol</td>
</tr>
</thead>
</HeaderTemplate>
<ItemTemplate>
<tbody>
<tr runat="server" ID="trOption">
<td class="GridRow"><asp:Label runat="server" ID="lblOptionAccount"></asp:Label></td>
<td class="GridRow"><asp:Label runat="server" ID="lblOptionMargin"></asp:Label></td>
<td class="GridRow"><asp:Label runat="server" ID="lblOptionSymbol"></asp:Label></td>
<td class="GridRow"><asp:Label runat="server" ID="lblOptionUsymbol"></asp:Label></td>
</tr>
</tbody>
</ItemTemplate>
</asp:Repeater>
Now, in my code-behind I have an event which is fired that is supposed to add/insert a row into the database. After this happens, I re-grab the new list of options from the database and re-bind them to the repeater. This takes place inside an update panel so the list refreshes right away for the user.
protected void lbtnAddOptionSave_Click(object sender, EventArgs e)
{
SelectedOption = new Option()
{
Account = txtAddOptionAccountNumber.Text,
Margin = chkAddOptionMargin.Checked,
Symbol = txtAddOptionSymbol.Text,
Usymbol = txtAddOptionUsymbol.Text,
};
Presenter.OnAddOption(); // Insert new option into database
RefreshOptions(); // Re-get list of options, bind them to repeater
}
Now, what I would ~love~ to do, is use the jQuery ScrollTo plugin to scroll straight to the newly added row.
What would be the best way to call the ScrollTo() method in the jQuery plugin so I scroll to that particular row that was just added? Is there anyway I can mark my rows in my ItemTemplate so I can easily select an element to scroll to via jQuery?
Ideally, right after RefreshOptions() I would like to execute the ScrollTo function to scroll down to the new row.
If you know the client side Id of the row (which you can get), its relatively painless to simply call
$(document).scrollTo("#<row-id-here>", 800);
When you add the object to the database (or just after that), grab the id of the newly inserted object. Modify the repeater to include a Label with Visible="false" so that it doesn't get rendered to the client. Hook into the ItemDataBound event and check each label against the id you've grabbed. When you find the matching row, you can get the id of the row and then you'll be able to use for the scrolling parameter.
Note: Other data-bound controls have a DataKey property which could be used for the id of the object and make this a bit simpler. Not sure if you're tied to the Repeater at this point, but a GridView or ListView could be worth looking into.

Categories