TextBox.Text property is not assigned in UserControl - asp.net

My UserControl code is below, I have one TextBox in UserControl and would like to access TextBox.Text property from web page.
UcUserForm user control is inserted in myform.aspx web page.
On myform.aspx PageLoad I set value for textBox like this
ucUserForm.TbFirstName.Text = "Tomas";
Everything works fine. When web page is loaded I see name inside textbox. Then I change value from Tomas to Jonas.
On myform.aspx ButtonClick I am trying to read value
var mynewname = ucUserForm.TbFirstName.Text;
despite that name is changed from Tomas to Jonas in TextBox on web page I still get the old name Tomas. Can't understand where is the problem.
UserControl code behind
public partial class UcUserForm: System.Web.UI.UserControl
{
public TextBox TbFirstName
{
get { return tbFirstName; }
}
}
UserControl web page
<asp:TextBox ID="tbFirstName" autocomplete="off" MaxLength="25" runat="server"></asp:TextBox>
Registration user control code in default.aspx
<%# Register Src="ucUserForm.ascx" TagName="ucUserForm" TagPrefix="uc1" %>
<uc1:ucUserForm ID="ucUserForm" runat="server" />

Try this:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
ucUserForm.TbFirstName.Text = "Tomas";
}
}

You set it every time you load the page. Try in Init stage.
Similar to this
protected void Page_Init(object sender, EventArgs e)
{
ucUserForm.TbFirstName.Text = "Tomas";
}
The Init just happens once in the Page's life cycle
http://msdn.microsoft.com/en-us/library/ms178472.aspx

Related

Page_Load Vs Page_Init for the user control in a Page

I have a ASP.NET page called customer.aspx which has a user control customerdetails.ascx inside of it. This user control reads data from the database and populate some fields. If the loading is successful (if there is some data), the user should stay on the page. Otherwise the page should be redirected to a different page. This redirection is done in the container customer.aspx page and not in the control.
What are the ASP.NET page cycle events (Page_Load Vs Page_Init) that I should use for customer.aspx and customerdetails.ascx for the above logic to work?
If you've established that both options work functionally, then, for performance, you should prefer Page_Init.
If you might end up with a redirect, then you want to give the server the chance to do that redirect as soon as possible in the page lifecycle, to avoid using resources on lifecycle steps that might not be necessary.
I was rereading this - https://web.archive.org/web/20210330142645/http://www.4guysfromrolla.com/articles/092904-1.aspx, old, but good. I think you should be able to do what you need from the Page_Load event of customer.aspx because user controls are loaded by then. simply check the user control's controls for values and redirect, or not.
edit:
Actually, I think it depends. controls prob have to be preloaded, which changes things.
If we need our dynamically added controls to maintain their view state it is paramount that these controls be added before the Load View State stage. That is, these controls must exist within the page's control hierarchy before the view state is loaded. There's only one stage before Load View State - Initialization. That means, if we want our dynamic controls to persist view state we must add them to the control hierarchy in the page's Init event.
One way to make the user control accessible (answer at bottom): https://forums.asp.net/t/1674095.aspx?Loop+through+User+Controls+in+Content+Page
edit:
User Control
<h4>The User Control</h4>
<div>
<asp:Label ID="lblUserCtrl" runat="server" Text="Label"></asp:Label>
</div>
.cs
public partial class Testing_Controls_TestCtrl : System.Web.UI.UserControl
{
// public properties
public Label lbl
{
get { return lblUserCtrl; }
set { lblUserCtrl = value; }
}
public bool isLoaded;
// end public properties.
protected void Page_Init(object sender, System.EventArgs e)
{
lblUserCtrl.Text = "User ctrl loaded at: " + DateTime.Now;
isLoaded = true;
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
container page:
note: I still had to register the control even though I loaded it from code.
<%# Register Src="~/Testing/Controls/TestCtrl.ascx" TagPrefix="uc1" TagName="TestCtrl" %>
...etc...
<form id="form1" runat="server">
<h4>The Container Page</h4>
<div>
<asp:Label ID="lblContainerLabel" runat="server" Text="Label"></asp:Label>
</div>
<br />
<hr />
<asp:PlaceHolder ID="ph1" runat="server"></asp:PlaceHolder>
</form>
.cs
public partial class Testing_user_control_test : System.Web.UI.Page
{
private bool ucIsLoaded;
protected void Page_Init(object sender, System.EventArgs e)
{
Testing_Controls_TestCtrl c = (Testing_Controls_TestCtrl)Page.LoadControl("~/Testing/Controls/TestCtrl.ascx");
ph1.Controls.Add(c);
c.lbl.Text += "<br />This is text appended to the user control by the container page.";
ucIsLoaded = c.isLoaded;
}
protected void Page_Load(object sender, EventArgs e)
{
lblContainerLabel.Text = "Container page loaded at: " + DateTime.Now + "<br />The user control is loaded: " + ucIsLoaded.ToString().ToUpper();
}
}

ASPX code behind ViewState not saving

I am trying to use ViewState to retain my textbox's input during a postback. Here's the code:
private Label store_Incident_Number = new Label();
private TextBox Incident_Number = new TextBox();
protected void Page_Load(object sender, EventArgs e)
{
if (ViewState["Incident_Number"] != null)
{
store_Incident_Number.Text = "TEST" + (string)ViewState["Incident_Number"];
Panel1.Controls.Add(store_Incident_Number);
}
}
void Page_PreRender(object sender, EventArgs e)
{
ViewState.Add("Incident_Number", Incident_Number.Text);
}
above code located in my default.aspx.cs (code behind). The Panel1 is an asp control some where on the web page outside of a form tag. I am trying to follow this example: https://msdn.microsoft.com/en-us/library/ms227551(v=vs.85).aspx
I was hoping the Incident_Number textbox's text is saved onto the label after the page is postback, but it doesn't seems to work and I couldn't figure out the problem. Note that the textbox is dynamically added to the form of the page and is recreated every postback. My question is how I code to retain the textbox's value after the page is being postback?
EDIT: Fixed! Please see my accepted answer. Also, any eventhandler
or other process that have potential to trigger another postback
during Page_Init will refresh your value saved in viewstate (i.e. saved text is gone).
As I mentioned in my comment, you're not letting the WebForms system work for you. Here's an example of a form with dynamically created controls maintaining viewstate. Per your description, the panel is outside the form.
When the page is displayed, you can enter new text and click submit repeatedly. The TextBox value will automatically be retained.
Default.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
</form>
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
</body>
</html>
Default.aspx.cs
using System;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
private Label store_Incident_Number = new Label();
private TextBox Incident_Number = new TextBox() { ID = "TextBox1" };
private Button SubmitButton = new Button() { ID = "Button1", Text = "Submit" };
protected void Page_Init(object sender, EventArgs e)
{
// what is created during this event has viewstate restored to it
Panel1.Controls.Add(store_Incident_Number);
form1.Controls.Add(Incident_Number);
form1.Controls.Add(SubmitButton);
}
protected void Page_Load(object sender, EventArgs e)
{
// the viewstate has already been restored so you can access the content of the TextBox
store_Incident_Number.Text = Incident_Number.Text;
}
}
That happens because the page load method runs before the prerender. You can Google asp.net page lifecicle to find more details.
What you are basically doing here is loading the label value before adding it in the viewstate.
Also, it would help if you could tell us how exactly are you making the postback. Because click events for example, are also a part of the page lifecicle and that might change a few things.

Add a HtmlGenericControl to master page from server code

I'm creating a website which allows users to log in. After logging in successfully, user's name should be displayed across each page, for example, at the top right corner. I have a ContentPlaceHolder on Master Page. An h3 tag would then be created and added into this ContentPlaceHolder.
Master Page:
<asp:ContentPlaceHolder runat="server" ID="UserNamePlaceHolder">
</asp:ContentPlaceHolder>
Login Page:
<%# MasterType VirtualPath="~/Master" %>
Login Class:
protected void Login_LoggedIn(object sender, EventArgs e)
{
ContentPlaceHolder userNamePlaceHolder =
(ContentPlaceHolder)Master.FindControl("UserNamePlaceHolder");
var h3 = new HtmlGenericControl("h3");
h3.InnerHtml = login.UserName;
userNamePlaceHolder.Controls.Add(h3);
}
I did debugging step by step. Nothing went wrong: no null or empty value, each variable was created. However, the user name was not displayed at all. Does anyone have an idea?
A cleaner and better approach would be to create a public property on the Master page:
public string UserName
{
get
{
return Literal1.Text;
}
set
{
Literal1.Text = value;
}
}
That's it place the literal with ID Literal1 anywhere you want on the master page:
<asp:Literal runat="server" ID="Literal1" />
You are already adding Master directive for strongly typing Master class, so now your login class would look like this:
protected void Login_LoggedIn(object sender, EventArgs e)
{
Master.UserName = login.UserName;
userNamePlaceHolder.Controls.Add(h3);
}
Hope this helps.

Wiring events on dynamically-loaded ASP.NET User Controls?

For a "dashboard" module I need to dynamically load user controls based on criteria as the user enters the page (role, etc). The problem is that the events are not being fired at all from the controls
As I understand it I need to load the controls in the OnPreInit method of the dashboard page, however I cannot get a reference to the Placeholder control at this point of initialization (i.e. I get a NullReferenceException); trying to load the Placeholder dynamically via Page.FindControl gives me, ironically, a StackOverflowException.
I've tried loading the controls in PreRender and OnInit as well but the events in the controls are not wired up properly and will not fire.
The code is basically this:
// this does not work; if I try to access the placeholder control itself
// ("phDashboardControls") I get a NullReferenceException, if I try
// Page.FindControl("phDashboardControls") I get a StackOverflowException
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
Control ph = Page.FindControl("phDashBoardControls"); // Placeholder
if (ph != null)
{
// GetControlsToLoad just instantiates the controls and returns
// an IList<Control>. Eventually it will have logic to
// determine which control needs to be loaded based on user role etc.
foreach (Control control in GetControlsToLoad())
{
ph.Controls.Add(control);
}
}
}
// IModularControl is a custom interface defining a single
// Initialize method to set up a control...
private void Page_Load(object sender, EventArgs e)
{
foreach (Control control in this.phDashboardControls.Controls)
{
if (control is IModularControl)
((IModularControl)control).Initialize(this.CompanyID);
}
}
I've successfully loaded controls dynamically in Page_Load before. The only thing I found I had to be careful of was to ensure that if I did a postback, the same controls were loaded in subsequent page_load to ensure that the view state didn't get corrupted... all events etc worked as expected. In my case the controls flow ended up something like this:
page_load - load control a
(do something which causes postback and event x to fire)
page_load - make sure you load control a
event_x - clear control a, load control b
(do something which causes postback)
page_load - make sure you load control b
...
it meant loading controls you fully intented discarding, but was the only way I could find to not corrupt the viewstate...
If you have a page with PlaceHolder1 and Label1 in it, then the following code causes the button click event to fire just fine:
protected void Page_Load(object sender, EventArgs e)
{
var dynamicButton = new Button() { Text = "Click me" };
dynamicButton.Click +=new EventHandler(dynamicButton_Click);
PlaceHolder1.Controls.Add(dynamicButton);
}
void dynamicButton_Click(object sender, EventArgs e)
{
Label1.Text = "Clicked button";
}
Behaves the same with a user control:
WebUserControl ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:Button ID="Button1" runat="server" Text="Click Me" onclick="Button1_Click" />
WebUserControl code behind:
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Clicked Button";
}
parent control that loads the child control:
protected void Page_Load(object sender, EventArgs e)
{
var dynamicControl = Page.LoadControl("~/WebUserControl.ascx");
PlaceHolder1.Controls.Add(dynamicControl);
}
Just FYI the issue had to do with validation; the events weren't firing properly because some of the validation controls (there were a ton) weren't configured to only apply to that control.

Link Button on ASP.NET user control not firing

I have a user control, which is added to another user control. The nested user control is built up of a GridView, an image button and a link button. The nested user control is added to the outer control as a collection object based upon the results bound to the GridView.
The problem that I have is that my link button doesn't work. I click on it and the event doesn't fire. Even adding a break point was not reached. As the nested user control is added a number of times, I have set image button to have unique ids and also the link button. Whilst image button works correctly with its JavaScript. The link button needs to fire an event in the code behind, but despite all my efforts, I can't make it work. I am adding the link button to the control dynamically. Below is the relevant code that I am using:
public partial class ucCustomerDetails : System.Web.UI.UserControl
{
public event EventHandler ViewAllClicked;
protected override void CreateChildControls( )
{
base.CreateChildControls( );
string strUniqueID = lnkShowAllCust.UniqueID;
strUniqueID = strUniqueID.Replace('$','_');
this.lnkShowAllCust.ID = strUniqueID;
this.lnkShowAllCust.Click += new EventHandler(this.lnkShowAllCust_Click);
this.Controls.Add(lnkShowAllCust);
}
protected override void OnInit (EventArgs e)
{
CreateChildControls( );
base.OnInit(e);
}
protected override void OnLoad(EventArgs e)
{
base.EnsureChildControls( );
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
CreateChildControls( );
}
}
protected void lnkShowAllCust_Click(object sender, EventArgs e)
{
this.OnCustShowAllClicked(new EventArgs ( ));
}
protected virtual void OnCustShowAllClicked(EventArgs args)
{
if (this.ViewAllClicked != null)
{
this.ViewAllClicked(this, args);
}
}
}
I have been stuggling with this problem for the last 3 days and have had no success with it, and I really do need some help.
Can anyone please help me?
My LinkButton wasn't firing it's Click event, and the reason was I had its CausesValidation property set to True. If you don't want the link to validate the form, be sure to set this to False.
Try adding your click event to the linkbutton tag:
<asp:LinkButton runat="server" OnClick="linkShowAllCust_Click" />
Or adding it to your Page_Load:
Page_Load(object sender, EventArgs e)
{
this.lnkShowAllCust.Click += new EventHandler(this.lnkShowAllCust_Click);
}
Is the usercontrol within the gridview? If so register the event handler on the gridview's onrowcreated event.
It appears that you have a viewstate issue. Because the control isn't there when the viewstate is loaded the application doesn't know how to hook up the event to be fired. Here is how to work around this.
You can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If IsPostBack Then
CreateMyControls()
End If
End Sub
I had the same issue. I had viewstate="false" on the page I was adding the control to. (on the aspx page)

Resources