Adding to page control collection from inside a user control - asp.net

I have an asp.net usercontrol which represents a "popup" dialog. Basically, it's a wrapper for the jQuery UI dialog which can be subclassed to easily make dialogs.
As part of this control, I need to inject a div into the page the control is used on, either at the very top or very bottom of the form so that when the popup is instantiated, it's parent is changed to this div. This allows "nested" popups without the child popup being trapped inside the parent popup.
The trouble is, I can't find a safe way to inject this div into the page. A usercontrol doesn't have a preinit event, so I can't do it there, and calling Page.Form.Controls.Add(...) in Init, Load or PreRender causes the standard exception "The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases."
I thought I had found a solution by using...
ScriptManager.RegisterClientScriptBlock(Page, Me.GetType, UniqueID + "_Dialog_Div", containerDiv, False)
... which seemed to work well normally, but recently a coworker tried putting an UpdatePanel inside the dialog and now she's getting the error "The script tag registered for type 'ASP.controls_order_viewzips_ascx' and key 'ctl00$ContentBody$OViewZips_Dialog_Div' has invalid characters outside of the script tags: . Only properly formatted script tags can be registered."
How are you supposed to add controls to the pages control collection from inside a user control?

I'm not sure why you really need to add this div to the page's form, but this should work:
Public Class WebUserControl1
Inherits System.Web.UI.UserControl
Private Sub UC_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
AddHandler Me.Page.Init, AddressOf Me.Page_Init
End Sub
Private Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs)
Dim dialogDiv As New Panel
dialogDiv.ID = "DialogDiv"
If Not Page.Form.Controls.Contains(dialogDiv) Then
Page.Form.Controls.AddAt(0, dialogDiv)
End If
End Sub
End Class
How to implement it in C#. I'm always getting the error The control
collection cannot be modified on Load, PreRender
I need a Literal Control to be added to my master page's head from a user control. The literal control will contain the css link.
Do you want to add the literal to the HeadContent-ContentPlaceHolder control in the master or to the page's header(the html head element)? However, here i show both.
Here's the codebehind of your UserControl:
public partial class UC_AddToMaster : System.Web.UI.UserControl
{
private void Page_Init(object sender, System.EventArgs e)
{
this.Page.Init += UC_AddToMaster_Init;
}
private void UC_AddToMaster_Init(object sender, EventArgs e)
{
Literal literal = new Literal{ Text = "Hi World!" };
// if you want to add it to the header of the page:
if (!Page.Header.Controls.Contains(literal))
{
Page.Header.Controls.AddAt(0, literal);
}
// if you want to add it to the master's HeadContent ContentPlaceHolder control:
var siteMaster = Page.Master as SiteMaster;
if (siteMaster != null)
{
if (!siteMaster.Head.Controls.Contains(literal))
{
siteMaster.Head.Controls.AddAt(0, literal);
}
}
}
}
For the HeadContent approach mentioned above i've provided following property in the master:
// in the master
public ContentPlaceHolder Head { get { return this.HeadContent; } }
Therefore i needed to cast the page's master to it's actual type(SiteMaster here) in the UserControl. Otherwise i couldn't access this property.

Usercontrol doesn't have a PreInit event, but nothing's stopping you from adding a handler to the Page PreInit event in your UserControl:
Page.PreInit += new EventHandler(Page_PreInit);
edit - you're right - you can't capture PreInit from a usercontrol, though I'm surprised you can't - but you can still change the page controls collection by adding code to the constructor of the UserControl. I tried this and it works.
public MyUsercontrol()
{
Page page = (Page)HttpContext.Current.Handler;
Literal lit = new Literal();
lit.Text="text";
page.Controls.Add(lit);
}
Adding an event handler to Page.PreInit in the constructor compiles but it never fires.
(end edit)
That said, I'm not exactly sure why this is necessary to achieve your goal. Why don't you just have your dialog control render it's own div in-line wherever you drop it into the form, and use that as the parent, instead of trying to create one somewhere else in the form? I can't think of why it would be important for it to physically be rendered at the beginning or end of the form. It's a dialog so it will always be invisible until you use it, right?

Related

Issues with Dynamically Loading a User Control

I am dynamically loading a user control on the page which works fine. However i am facing one problem:
I have a class level variable on the User Control code-behind and the value to the same is assigned in User Control Page Load. Now when i click the button on my aspx page which contains the user control in it and try to call the User Control function from it, i see the value of the variable which i had set in the user control-page load has been reset.
The same code works perfectly if i have the user control at design time.
Code is something like this:
Page:
MyUserControl cntrl = Page.LoadControl("~/MyUserControl.ascx")
btn_click(){
{
cntrl.TestFunction();
}
User Control:
class MyUserControl: UserControl
{
//Variable
string org="";
Page_Load()
{
org="test";
}
TestFunction()
{
//The value of org variable is empty here.
//It should however be "test" which i have set in page_load
}
}
"Code is something like this:" - when providing code (even as fragments), try to make it to comply with the language syntax - in this case C#.
In order for MyUserControl.Page_Load to fire, you have to add the user control to the control tree of the page:
MyUserControl cntrl = (MyUserControl)Page.LoadControl("~/MyUserControl.ascx");
Panel1.Controls.Add(cntrl);
The Page_Load method must have very specific signature and scope:
class MyUserControl: UserControl
{
string org="";
protected void Page_Load(object sender, EventArgs e)
{
org="test";
}
}

How can I access my Mater Page's radtabstrip?

I have a master page with a radtabstrip I use as my main navigation. In a content page I'd like to be able to disable/enable a tab from that strip. I've tried using findControl but I think it's returning null. Here's my code:
RadTabStrip menuStrip = (RadTabStrip)Master.FindControl("tabMain");
menuStrip.FindTabByText("Lookup Table").Enabled = true; //null reference error occurs
Fairly simple, but I'm guessing referencing an object like a radTreeStrip isn't the same as a label or textbox..any ideas?
EDIT:
I actually got it to work by making a function on my master page and calling it from the content page. However, what I REALLY need is to access the master page from a page that is not implementing the master page. Would that be possible? Or is there a way to include the master page but not show it's contents? –
You must first select the Page.Master and convert it to a MasterPage; next you load the control using FindControl, then convert it to a RadTabStrip, like so:
VB.NET
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Dim menuStrip As RadTabStrip = CType(CType(Page.Master, MasterPage).FindControl("tabMain"), RadTabStrip)
End Sub
C#
Proected void Page_Load(Object sender, System.EventArgs e)
{
RadTabStrip menuStrip = (RadTabStrip)((MasterPage)Page.Master).FindControl("tabMain")
}
EDIT:
If you want the same RadWindow to be used across multiple pages, make sure you make a different aspx page and add its URL inside the NavigateUrl of the RadWindow.
Below is a link from Telerik that displays info about the RadWindow and its NavigateUrl:
http://demos.telerik.com/aspnet-ajax/window/examples/contenttemplatevsnavigateurl/defaultcs.aspx

Property null after postback - Dynamically loaded control

I'm aware this question has been asked many times before but I suspect I have a unique scenario.
I'm loading a Child Control (ASCX) and setting a Property on that Control. This works perfectly fine until postback where the property is null.
Herewith the First Class which loads the ChildControl :
protected override void CreateChildControls()
{
MyUserControl control = (MyUserControl)Page.LoadControl(_ascxPath);
control.MyProperty = base.MyProperty
Controls.Add(control);
}
Then, on my Child Control I've got the following code:
public partial class MyUserControl : UserControl
{
public MyType MyProperty { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
//Exception on next line because Property is null (only on postback)
var somevalue = MyProperty.SubProperty;
Ok. Let me try to explain it.
1. Once page is created, you get full page lifecycle
2. You click on some control to create user control, and you get it
3. Now you are entering value to this control, and getting postback
4. On server side postback is handled, but as you can see viewstate actions appear as soon as page is loaded.
One of main purposes of viewstate is handling control events, to see if they are changed, or save their states or something else.
5. If on the moment, when viewstate is loaded you control is still not constructed, then all it's events and values would be ignored.
Solution either make it static control and just hide it, either create it before viewstate actions started.
You need to add the control and set properties in the Page_Init event, other wise you will lose the properties value.
In Microsoft explanations about ASP.NET page life cycle, it is written that dynamically created controls must be created in PreInit.
It worked for me.
Here is my main page :
protected global::System.Web.UI.HtmlControls.HtmlGenericControl FiltersZone;
(. . .)
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
FiltersZone.Controls.Add(new PlanningFiltersSurgeonWeb());
}
This dynamically created ".ascx" control contains an hidden field :
<input id="hidTxtPaint" type="hidden" name="hidTxtPaint" runat="server" />
I am now able to retrieve its value from within dynamically created ASCX control Page_Load event, after a "submit" or a "__dopostback('hidTxtPaint')" initiated from JavaScript.
On the other hand, the hidden field's value is always empty after a POST if its parent ".ascx" control is added in main page's Page_Load event.

asp.net use class object on form

I am creating an object at server side of an aspx (test.cs) page from a class (asp.net 2.0 C#)
public partial class Vendor_VendorUsedTicketsPopup : System.Web.UI.Page
{
ReportInvoice _objReportInvoice = new ReportInvoice();
protected void Page_Load(object sender, EventArgs e)
{
_objReportInvoice.ReportId = 1;
}
}
as you see above before Page Load I am creating a new ReportInvoice object and on page load I am setting property ReportId to 1
On test.aspx I want to use the ReportId value bu using the _objReportInvoice object like below
<div><% _objReportInvoice.ReportId; %></div>
But when I build the site I get the error
The name '_objReport' does not exist in the current context
I know that I can create a public integer for ReportId above Page_Load and use it on aspx page. That works fine , but I want to use class object properties on aspx page.
What is the way of doing sth like that ?
Thanks...
You need a = sign in there to print it to the page:
<div><%= _objReportInvoice.ReportId; %></div>
However, I would suggest just using a Literal or Label control there and then setting it's text to the ReportID property in the code behind. Inline code like that can make your HTML messy.
Remember that your .ASPX markup page inherits from the codebehind class.
This means that unless you declare your field as protected or public, the .aspx will not have access to your field.
You need to add an access modifier to your field to make it non-private.

ASP.NET WebControl & Page - Adding controls (like TextBox) dynamically

I'm trying to create a custom server control (WebControl) with a text box.
I add asp.net textbox to the custom control in CreateChildControls override. In OnInit override I add event handler to TextBox.TextChanged.
Everything works, except that TextChanged never fires. I looked at viewstate and it looks like my textbox never saves its Text property in the viewstate. I've tried to set Text in various places, including constructor, but nothing works.
How can I get TextBox dynamically added to WebControl to save it's Text in viewstate and get TextChanged event to fire?
I would greatly appreciate an example of WebControl code behind with TextBox being added dynamically and TextChanged event being fired.
The dynamically created control must be created again in each post back, (the pageInit event is the better option) for the event to be fired.
BTW, if you want the TextChanged event to generate a postback you must also set the AutoPostback of the control to true.
fixed it. dynamic control must be created and added in Init event. It must be assigned an ID without special ASP.NET symbols ('$' or ':' inside custom ID will break things). All properties must be assigned after control is added to the controls tree.
here's a working example for Page codebehind:
private readonly TextBox _textBoxTest = new TextBox();
protected void Page_Init( object sender, EventArgs e )
{
this.form1.Controls.Add( _textBoxTest );
_textBoxTest.Text = "TestBoxTest";
_textBoxTest.ID = "TestBoxTestId";
_textBoxTest.TextChanged += this._textBoxTest_TextChanged;
}
void _textBoxTest_TextChanged( object sender, EventArgs e )
{
_textBoxTest.Text = "Worked";
}
for WebControl place init code in OnInit override
This will help you out. In short, you need to handle the viewstate for your Dynamically added control on your own.

Resources