I am new to ASP.NET programming.
I would like to add controls to my current page when a button is clicked.
Currently, this is the event that gets fired:
protected void Button_Click(object sender, EventArgs e) {
LiteralControl litctrl = new LiteralControl("<div> Testing " + DateTime.UtcNow.Millisecond +" </div>");
form.Controls.Add(litctrl);
}
This works fine on the first click but if I click again, I do not get an extra div added to the form. A new div is created but the previous one is lost.
Why is it so and how can I create controls additively on the current page ?
See http://chiragrdarji.wordpress.com/2009/05/20/maintain-viewstate-for-dynamic-controls-across-the-postback/ for some examples. Adding dynamic controls in ASP.NET Webforms is a tricky dance between understanding postbacks and the page lifecycle. Throw in any ViewState requirements and it takes some even deeper understanding.
For your requirements, you need to recreate any dynamically added controls on every postback. As you aren't, it disappears.
This technique is often known as adding "Dynamic" controls.
Examples include:
http://www.stev.org/post/2011/03/02/ASPNET-Dynamic-Controls.aspx
https://web.archive.org/web/20211020131055/https://www.4guysfromrolla.com/articles/081402-1.aspx
http://weblogs.asp.net/infinitiesloop/archive/2006/08/25/TRULY-Understanding-Dynamic-Controls-_2800_Part-1_2900_.aspx
http://geekswithblogs.net/shahed/archive/2008/06/26/123391.aspx
http://support.microsoft.com/kb/317794
It is also important to understand the ASP.Net Page Lifecycle - when a control is added is often very important.
Common Pitfalls are covered widely, for example:
Control Add PostBack Problem
problems with postbacks events from dynamic controls in ASP.Net
http://www.singingeels.com/Articles/Dynamically_Created_Controls_in_ASPNET.aspx
http://www.codeproject.com/Articles/3684/Retaining-State-for-Dynamically-Created-Controls-i
Related
I'm writing code to read data from asp controls to update records in a database. I've been debugging the last day and I've tracked it back to something that I ought to have noticed before.
The code first populates the controls with the existing values from the database.
When I click SAVE, it should read the current values from the controls and save with those.
Unfortunately, what it's actually doing is using the values of the controls before a change was made to them. It's not seeing the change to the controls.
Here's a sample:
<asp:TextBox ID="OtherCourseName_5" runat="server"></asp:TextBox>
Here's the corresponding behind code in the btnSave_onClick() function:
int object_number=5;
string other_course_name_string
= "OtherCourseName_" + object_number.ToString().Trim();
TextBox ocn = utilities
.utils
.FindControlRecursive(this.Master, other_course_name_string) as TextBox;
I'm using the FindControlRecursive() I found somewhere on the web. It works, I'm sure, but just in case, I tried to address the control directly as OtherCourseName_5.Text.
Even if I just display the value in OtherCourseName_5.Text, it gives the original value.
I use this same page for both entering new data and for editing data. It works fine when I enter the data. That is, it correctly sees that the TextBox control has changed from empty to having data. It's only when I invoke the edit function on the page (by passing edit=true). I invoke it this way by adding the switch edit=true as a query string (the program correctly reads that switch, gets to the appropriate area of code, prints out all the correct values for everything - except the contents of the controls!).
The page is far too complicated to post the entire thing. I've tried to convey the essential details. It's entirely possible that I've made a simple coding error, but it's seeming more a possibility that I fundamentally misunderstand how pages are processed.
Is there anything known that can make it seem as though the value of a control has not been changed?
Note 1: I thought perhaps I had to go to another field after I entered the data, but I tried that and it's still a problem.
Note 2: I'm using both TextBox and DropDownList controls and have the same problem with both.
Note 3: These controls are on a panel and the page is using a SiteMaster. I haven't had any problem with that and don't think the problem is there, but I'm down to questioning the laws of the physics at this point.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//populate controls with data from database
}
}
When you do a postback before the postback handler is evaluated the PageLoad event is raised
so if you don't avoid to rebind your control they will be loaded with the values from the database. And then the postback event will save them to db
Asp.net Page Lifecycle
(source: microsoft.com)
In my ASCX, I have an asp.net hidden field defined as <asp:HiddenField ID="hdnNewAsset" runat="server" />.
In the Code Behind I have the following code:
protected void Page_Load(object sender, EventArgs e)
{
_service = new ArticleDataService(PortalId);
if (!IsPostBack)
{
string rawId = Request[ArticleQueryParams.ArticleId];
DisplayArticleDetails(rawId);
}
if (hdnNewAsset.Value.Trim() != string.Empty)
ProcessNewAsset();
}
Now, in my frontend, I have a javascript function to react to an event and set the hidden field and trigger a postback:
function assetSelected(assetGuid) {
$('input[id*="hdnNewAsset"]').val(assetGuid);
__doPostBack()
}
What's happening is that my hidden field is being set in the markup (chrome shows [
<input type="hidden" name="dnn$ctr466$Main$ctl00$hdnNewAsset" id="dnn_ctr466_Main_ctl00_hdnNewAsset" value="98d88e72-088c-40a4-9022-565a53dc33c4">
] for $('input[id*="hdnNewAsset"]')).
However, when the postback occurs, hdnNewAsset.Value is an empty string.
What's even more puzzling is that at the beginning of Page_Load Request.Params["dnn$ctr466$Main$ctl00$hdnNewAsset"] shows 98d88e72-088c-40a4-9022-565a53dc33c4, and after the postback my hidden field has the same value (so the hidden field is persisting across postbacks), yet I cannot access this value via hdnNewAsset.Value.
Can anyone see what I"m doing wrong?
Ok I figured out the the issue.
The issue is that the code posted above was part of an ASCX user control. That user control was being loaded dynamically into an asp.net placeholder during the Page_Load event of the parent control.
Therefore, it seems that since both of these calls were in Page_Load of their respective calls, the inner control did not have it's values bound in the inner control's page_load. Modifying it so my inner control is loaded in Page_Init instead of Page_Load fixed all bindings.
Not sure if I wrote that in a way that makes sense to the general public.
Edit: It seems this part of the MSDN documentation is relevant to my issue:
If controls are created dynamically at run time or declaratively within templates of data-bound controls, their events are initially not synchronized with those of other controls on the page. For example, for a control that is added at run time, the Init and Load events might occur much later in the page life cycle than the same events for controls created declaratively. Therefore, from the time that they are instantiated, dynamically added controls and controls in templates raise their events one after the other until they have caught up to the event during which it was added to the Controls collection.
I'm having trouble implementing a functionality on my c#/asp.net app.
I have a form with a RadioButtonList and a submit button.
The RadioButtonList is generated on Page_Load() from a list of objects I retrieve from the database.
I would like to automatically submit the form if there is only 1 object in the list.
I have access to my Form object, to the submit button etc... but I can't seem to find a solution (in the end I'm looking for a kind of form.Submit() ) method.
Does anyone have an idea of how I could do this ?
Thanks in advance !
EDIT >> Here is the code :
.aspx : http://pastebin.com/0E6T7dqH
.aspx.cs : http://pastebin.com/54payZJP
EDIT2 >>>
As it seems there is no way to do what I wanted to do at first, I ended up using a session variable with a response.redirect()
Source :
http://dotnetslackers.com/Community/blogs/haissam/archive/2007/11/26/ways-to-pass-data-between-webforms.aspx
Post happens in the client side. As in Page_Load you are currently executing in the server side, just call the code you want to execute on post.
Edit: For actually going to another aspx
public void Page_Load(object sender, EventArgs e) {
if(!IsPostback && OnlyOneItem) {
Server.Transfer("TheOtherPage.aspx");
}
}
Server.Transfer will maintain the entire request, so your post data will be available.
http://msdn.microsoft.com/en-us/library/system.web.httpserverutility.transfer.aspx
Try something like this
In your Page_Load
if(!IsPostBack)
{
if(check for only one object)
{
//your submit code
}
}
I actually had to do something similar, once. Here is a way you can do it.
Asp.Net buttons have a property called PostBackUrl, and it does exactly what you would expect - it controls where the form will post if you click the button.
You can also use the RegisterStartupScript function to render javascript on the page.
Now, with these two pieces, you can achieve your goal.
if(!IsPostBack)
{
if(results == 1)
{
button.PostBackUrl = "next page's url"
//Register script to click the button using RegisterStartupScript
}
}
Now, having shown you this, I will warn you it may not make for the best user experience. When I did it, it was for a very specific case that had no other solution. The page will actually post back to the user, and they will see the page for a moment before the javascript to click the button takes effect. Additionally, when you set a button's PostBackUrl, that means that when it is clicked, your entire form will be posted to the page specified. The code behind for the current page will not fire at all, so if you have any validation, it won't run.
There's nothing wrong with letting the user click the button to submit the form even if they only have one choice. In my experience, users like to feel like they are in control on the system; they don't like it when pages just do things without their input.
Also, there is not really anything wrong with putting the information the next page needs into the session or even a database table, and using Response.Redirect. It's a fairly common practice and works reliably in most scenarios.
I'm trying to get the values of dynamically generated FileUpload controls that I add to a Panel:
<asp:Panel ID="pFileControls" runat="server">
</asp:Panel>
I create the controls during a loop through a record set:
foreach(DataRow dr in ds.Tables[0].Rows)
{
FileUpload fu = new FileUpload();
fu.ID = dr["SomeID"].ToString();
pFileControls.Controls.Add(fu);
}
Everything works fine up to the point where I submit the form with this button:
<asp:Button ID="btnImportFile" runat="server" Text="Save" OnClick="btnImportFile_Click" />
Which I register like this (Page_Load):
ScriptManager.GetCurrent(this).RegisterPostBackControl(btnImportFile);
I do this because I'm using a MasterPage/ContentPage setting in my website and mostly everything happens inside an UpdatePanel for AJAXification purposes. Bear in mind that if I explicity specify a FileUpload Control in the HTML view, it works 100%.
When the form is submitted I try to iterate the Panel like this:
foreach (Control ctrl in pFileControls.Controls)
{
if (ctrl.GetType() != typeof(FileUpload))
{
continue;
}
//Do the saving of the file here
}
Except, the Panel seems to only return one control: The Content Place Holder for the page and nothing else. Does anyone have some ideas about this?
What part of the life cycle are you adding the dynamic controls?
if you are putting them in the page_load it may be too late, try putting the generation of the dynamic controls into the page_init and see if that fixes the problem.
page lifecycle
http://msdn.microsoft.com/en-us/library/ms178472.aspx
dynamic controls
http://geekswithblogs.net/shahed/archive/2008/06/26/123391.aspx
Note:
"Its recommended to load the dynamic
controls during the Page_Init instead,
because we may want to hook up our
events with proper handler at an early
stage. ... Do not assigning
properties of a dynamic control
(viewstate enabled), during Page_Init,
it will not be reflected. "
I would expect that even with the update panel, you will need to be mindful of the page_load limitations with dynamic controls.
let me know if this helps or if I missed the mark!
Let's try a different course of action (I've gotten dynamic file upload to work, but it was a bear and I wish I had simply used this)
http://www.asp.net/ajaxlibrary/act_AsyncFileUpload.ashx
or
http://en.fileuploadajax.subgurim.net/
these may not create a 'loop' of elements, but you can simply keep loading docs on a as-needed basis.
I have specifically used
http://www.asp.net/ajaxlibrary/act_AsyncFileUpload.ashx
to great effect.
There also appear to be some limitations to the update:panel and the file upload, check out these sites.
(this one says it does not work in partial update status but does work in full postback)
http://forums.asp.net/p/1105208/1689084.aspx
do you know if the submit is triggering the full page or just the update:panel? (check out this: http://geekswithblogs.net/mmintoff/archive/2009/04/01/fileupload-within-updatepanel.aspx
I'm trying to edit a textbox's text in a Page_Load form on an ASP.NET page, but when I try to edit TextBox1.Text it throws a NullReferenceException because the TextBox has not yet been instantiated. Specifically what I'm trying to implement is this: http://www.codeproject.com/KB/user-controls/popupcalendarcontrol.aspx but it is written for an older version of ASP.NET and does not work for me. Is there a way to instantiate the controls at the start of Page_Load? or another event that I can catch on load? With a normal windows form I would call InitializeComponent() in the constructor.
There are absolutely different events you can attach to but it sounds like the page isn't loading the controls properly because they should be available by that point. You can take a look at the ASP.NET Page Life Cycle for more information.
Does the TextBox sit within a bound control, such as a FormView, GridView, DataList, etc? If so, then the control won't exist until after the databinding happens. Once that event happens, you can do something like
DirectCast(myDataList.SelectedRow.FindControl("myTextBox"),
TextBox).Text
I know that I am a bit behind in getting to this question BUT I have found something unusual that I can NOT find documented anywhere. It would appear that IF your page is "under" a Master Page, and IF you refer to ANYTHING on said master page, the controls to your current page are null - EVERYONE of them. I found this out by referencing "Master.Environment" - a public string - during my InitializeCulture method and having the FIRST control on my current (Default.aspx) page be null during Page_Load() - WHATEVER the first control was.
I know I am late but if this can help ANYBODY, I want the word out.