Placeholders Not Instantiated when adding Controls Programmatically - c#

I have a an ASPX Page with a Placeholder control declared.
In the Codebehind I create a UserControl I have and add it to the Placeholder.
protected void Page_Load(object sender, EventArgs e)
{
UserControl uc = new ChartUserControl();
myForm.Controls.Add(uc);
}
The UserControl in turn has a Placeholder, but in the Page_Load (for the UserControl) when I do:
protected void Page_Load(object sender, EventArgs e)
{
WebControl x = new WebControl();
userControlPlaceholder.Controls.Add(x);
}
It gives me the ubiquitous "Object reference not set to an instance of an object" exception.
I've tried forcing instantiation by calling a constructor, but that has gotten me into other trouble. Any help would be appreciated.

I just spent 4 hours on this myself.
The problem is that you're creating the user controls with
ChartUserControl chart = new ChartUserControl();
but you have to use LoadControl:
ChartUserControl chart =
(ChartUserControl)LoadControl("~/path/to/control/ChartUserControl.ascx");
Apparently, LoadControl initializes the user control so that its PlaceHolders (and I would assume, other controls it contains), won't be null when you use them.

Instead of adding the control in the Page_Load, Override the CreateChildControls method and add it there.

Related

can't able to add value to textbox

I have a datacontrol.cs(UserControl), which is contain textbox1 and codebehind window having a method with parameter of currentvalue
public void bindvalue(float currentvalue)
{
textbox1.Clear();
textbox1.Text = currentvalue.ToString();
}
I have a Form, Here added the usercontrol in this form and which contains a Button
So when clicking button it pass a currentvalue by the way of method to the datacontrol class like that .
private void button_click(object sender, EventArgs e)
{
float currentvalue = 1500.00f;
datacontrol obj = new datacontrol();
obj.bindvalue(currentvalue);
}
Everything working fine to me. It pass the current value to the usercontrol class and there current value assigned/added to the textbox1.Text = currentvalue.ToString();. It doesn't shows any error . But finally the textbox doesn't shows any value.
I used breakpoint to check the functionality. It gave current value to the textbox. But strange!!!..
I can't predict whats wrong in my code.
Helps appreciated.:)
Your instance of datacontrol with required value (1500.00f) does not exist on your form. You are only delcaring it, passing value and forgetting about it.
If you have already added user control to form and want to call bindvalue method of existing control, you should do the following:
private void button_click(object sender, EventArgs e)
{
float currentvalue = 1500.00f;
this.dataControl1.bindvalue(currentvalue);
}
Note that dataControl1 is the name of your user control on the form, it can be different from dataControl1.
If you want to create new user control and call bindvalue, you should add new instance on the form:
private void button_click(object sender, EventArgs e)
{
float currentvalue = 1500.00f;
datacontrol obj = new datacontrol();
obj.bindvalue(currentvalue);
this.Controls.Add(obj);
}
If it is already dynamically added control on the form, declare a field of Form class, assign new instance of it control, when you want it, and call to it as it shows in the first example.
You need add instance of datacontrol to the form
datacontrol obj = new datacontrol();
obj.bindvalue(currentvalue);
Controls.Add(obj);
You can simply make a call to bindvalue method by using the tagename of your user control in button click event handler.
Suppose the tag name is 'datacontrol', then you should use the following lines of code to achieve your task:
protected void Button1_Click(object sender, EventArgs e)
{
float myvalue = 150.50f;
datacontrol1.BindValue(myvalue);
}
Regards, Aamir ( .Net developer)
Please marks this thread as answer if it solved what were looking for... thanks

How to find a control inside an asp.net calendar control

After adding a control in the dayrender event, is there a way to find the control later? I have tried
calendar.FindControl("lblSample")
but without success.
Here is some of my code to be more clear:
protected void calSample_DayRender(object sender, DayRenderEventArgs e)
{
Label lblSample = new Label();
lblSample.ID = "lblSample";
lblSample.Text = "Sample";
e.Cell.Controls.Add(lblSample);
}
After the day render event and the page loads completely, I have a link button event where I try and get the control back
protected void lbtnSave_Click(object sender, EventArgs e)
{
//Not working
Label lblSample = calSample.FindControl(lblSample);
//Also can't get to work, this was using Ross' suggestion and the recursive find function he wrote about. I'm probably just not using it correctly.
Label lblSample = ControlFinder.FindControl<Label>(calSample, "lblSample");
}
The issue was because the control was not added to the page until the dayrender method - meaning you could not get a reference to it on a post back. Using the Page.Request.Params collection the OP was able to grab the value out on the postback.
The problem is that the find control is not recursive and the control you want is probably inside another control.
This shows you how to make a recursive find control method that would help: http://stevesmithblog.com/blog/recursive-findcontrol/
Alternatively if you post the calendar controls code I can probably help you a bit more.
Ross
This answer is because of Ross' comment above showing me that I could use the Page.Request.Params to find the value I was after. It's not the cleanest solution but it works!
If you add a dropdownlist to a calendar control in the day render event
protected void calSample_DayRender(object sender, DayRenderEventArgs e)
{
DropDownList ddlSample = new DropDownList();
ddlSample.ID = "ddlSample";
ddlSample.DataSource = sampleDS;
ddlSample.DataBind();
e.Cell.Controls.Add(ddlSample);
}
You can get the selected value back like this, of course I need to put in more checks to verify that the dropdownlist exists, but you get the picture
protected void lbtnSave_Click(object sender, EventArgs e)
{
string sampleID = Page.Request.Params.GetValues("ddlSample")[0];
}

ASP.NET: rendering content after master is already rendered

I have a button on a content page which is suppose to modify the value of a textbox on the master page. The setup is simple enough.
Content Page - Code Behind - Button Click Handler:
protected void but_mybutton_Click(object sender, EventArgs e)
{
string new_value = "!!";
Master.textbox_value(new_value);
}
The problem is that by the time it get to that function, the master's page is already rendered. To get the new value to display, I would need to re-fresh the page. Is there anyway to explicitly tell a page to re-render because I have changed some values on it's controls without having to re-fresh the page?
The master page renders indeed like it's a control on the page.
This blogpost shows you the full page life cycle including the events of the master page.
http://weblogs.asp.net/ricardoperes/archive/2009/03/08/asp-net-page-events-lifecycle.aspx
From the code you have provided this should work as the OnClick handler of the button gets executed before the OnPreRender of the masterpage. Can you show us the code of what
Master.textbox_value(new_value);
does?
I just tested this with the most simple setup. On the masterpage 1 label and a method that sets the text of the label.
public partial class SiteMaster : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e) {}
public void SetLabelText(string text) {
this.Label1.Text = text;
}
}
On the content page a button. The onclick handler of the button calls the method on the masterpage.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) {}
protected void Button1_Click(object sender, EventArgs e)
{
((SiteMaster)this.Master).SetLabelText("foo");
}
}
This sets the text of the label in the same postback as expected.
You will need to review the ASP.NET Page Life Cycle to get a better understanding of how the events are firing.
Your best bet is to try setting the value on the page OnInit or LoadViewstate events.

How do I attach an event handler to an ASP.NET control created at runtime?

Good morning everybody.
I have a question connected with controls and event handling. Lets say I want to create a LinkButton.
protected void loadLinkButton()
{
ContentPlaceHolder content = (ContentPlaceHolder)this.Master.FindControl("MainContent");
LinkButton lnk = new LinkButton();
lnk.ID = "lnikBtn";
lnk.Text = "LinkButton";
lnk.Click += new System.EventHandler(lnk_Click);
content.Controls.Add(lnk);
}
Here is the event handler:
protected void lnk_Click(object sender, EventArgs e)
{
Label1.Text = "ok!";
}
If I run the loadLinkButton function inside Page_Load everything is ok. But when I try to run the loadLinkButton by clicking simple button, link button is created but event is not handled.
protected void Button1_Click(object sender, EventArgs e)
{
loadLinkButton();
}
I there any way to solve it? Or loadLinkButton must always regenerated on Page_Load, Page_init etc.
When working with dynamic controls, I always add the control in Page_Init, because viewstate loading will happen right after Init. If you add it to Page_Load, there is a chance that you will lose viewstate. Just make sure you provide a unique control ID.
It is important to know how ASP.Net determines which events to invoke. The source of each event is passed using a hidden field:
<input type="hidden" name="__EVENTTARGET" value="" />
Whenever the page loads, it pulls in the source of the event from that field and then determines which event to invoke. Now this all works great for controls added through markup because the entire control tree is regenerated on every request.
However, your control was only added once. When a Postback occurs, your control no longer exists as a Server control in the tree, and therefore the event never fires.
The simply way to avoid this is to make sure your Dynamic Controls are added every time the page loads, either through the Page_Init event, or the Page_Load event.
You are right. This is the expected behavior. Page_Load and Page_Init would be the events where you should be adding it.
That would be because when you click your dynamically generated linkbutton, you do a postback to the server. There you do an entirely new pageload, but your original buttonclick (that generates the link) never happened now, so the linkbutton is never made, and the event can not be thrown.
An alternative is to add the linkbutton you add dynamically, to your page statically, with Visible = false. And when you click the other button, make it visible.
I am not exactly sure what problem you are facing but you should put the dynamic controls code in Page_Init as suggested by #johnofcross:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_Init(object sender, EventArgs e)
{
CreateControls();
}
private void CreateControls()
{
var lb = new LinkButton();
lb.Text = "Click Me";
lb.Click += lb_Click;
ph.Controls.Add(lb);
ph.DataBind();
}
void lb_Click(object sender, EventArgs e)
{
lblMessage.Text = "Button is clicked!";
}
}

Add a control to the page header in ASP.NET

I'm creating a custom script control in ASP.NET
The purpose of the control is simply a server variant of the tag, used to load javascript files
The main purpose of this control however is to combine multiple scripts into one response so on the client side they see something like
tag for each location, so all scripts registered in the DocumentTop location will be combined into a single tag with the exception of the location "inline", all inline scripts are rendered individually where they exist in the markup
I have also created an httphandler, js.ashx, that does the actual combining of the scripts
Everything is working fine except for the "Head" location, for the two document locations i simply use the ClientScriptManager during prerender but for the Head location i have tried the following code during pre render
var scriptControl = new HtmlGenericControl("script");
scriptControl.Attributes["language"] = "javascript";
scriptControl.Attributes["type"] = "text/javascript";
scriptControl.Attributes["src"] = src;
Page.Header.Controls.Add(scriptControl);
and I get the following error:
The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
does anyone know how add a control to the page header from within a custom control?
Incidentally, the control is used on a content page that has two nested masters and also has a ScriptManager registered on the root master.
The project is an asp.net 3.5 web application project
Ive discovered an answer to my question.
I don't quite understand the why but the problem lies in when I am trying to add my script control into the head, doing it in the control's PreRender event causes my error but if you add the control during the Page's PreRender event it all works fine and dandy
eg:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.Page.PreRender += new EventHandler(Page_PreRender);
}
void Page_PreRender(object sender, EventArgs e)
{
var scriptControl = new HtmlGenericControl("script");
Page.Header.Controls.Add(scriptControl);
scriptControl.Attributes["language"] = "javascript";
scriptControl.Attributes["type"] = "text/javascript";
scriptControl.Attributes["src"] = "blah.js";
}
I don't know why you get this error but how about using ClientScript like that :
protected void Page_Load(object sender, EventArgs e)
{
string scriptFile = "myscriptFile.js";
if (!this.Page.ClientScript.IsClientScriptIncludeRegistered("myScript"))
{
this.Page.ClientScript.RegisterClientScriptInclude("myScript", scriptFile);
}
}
ClientScriptManager.RegisterClientScriptInclude Method
protected override void OnInit(EventArgs e)
{
EnsureChildControls();
base.OnInit(e);
}
protected void Page_Load(object sender, EventArgs e)
{
HtmlGenericControl js = new HtmlGenericControl("script");
js.Attributes["type"] = "text/javascript";
js.Attributes["src"] = yol.ScriptYol("jquery-1.3.2.min.js");
this.Page.Header.Controls.Add(js);
}

Categories

Resources