I have an ASP.NET user control that is used in another use control. The parent user control uses data-binding to bind to a custom property of the child user control.
What method can I override or page event where I am ensured that the property state is set?
I think in a page it is PageLoaded versus the Page_Load override? I am looking for this in the user control because my property is always null even though it is set.
Thanks.
Example. This is in my user control. FilterEntryId is being bound from inside another user control:
protected int _filterEntry = -1;
public int FilterEntryId
{
get
{
return _filterEntry;
}
set
{
_filterEntry = value;
}
}
protected void Page_Load(dobject sender, EventArgs e)
{
FilterEntry always -1!!
}
The property is being set but never has value when Page_Load. The Page_LoadComplete may be the proper place but does not seem to be an option in user control. I've also tried Page_DataBind.
My hypothesis is that this is a page lifecycle issue but it may be something else.
Not sure what you need to do with that property but since you can't be sure when will be set. Can't you add your logic on the set of the property?
Another option would be a later event as PreRender.
public int FilterEntryId
{
get
{
return _filterEntry;
}
set
{
_filterEntry = value;
//HERE YOUR LOGIC
}
}
Related
I have a custom control in a page which uses full and partial output caching. If I simply refresh the page, the control is loaded from cache (I've added a timestamp to verify that). But if I do an action in the control that causes PostBack, the second time I do it the ViewState "loses" a value that was added in Page_Load when !IsPostBack. I wonder if there is some way to have both ViewState and OutputCache working in this way.
public partial class MyUserControl : MyBaseUserControl
{
private string MyProperty
{
get { return (string)ViewState["_myProperty"]; }
set { ViewState["_myProperty"] = value; }
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
var prop = this.MyProperty;
}
protected void Page_Load(object sender, EventArgs e)
{
// Do something
if (IsPostBack)
{
var value = this.MyProperty; // sometimes gets null
}
else
{
this.MyProperty = GetNewValue(); // never returns empty or null
}
}
}
Edit: After posting the question, SO showed other related questions (like this), so I've reviewed Page Life Cycle and overriden LoadViewState method, and set breakpoints. When page (and control) is first loaded, Page_Load is called, but LoadViewState not; in first PostBack, LoadViewState is called and MyProperty has the correct content; in second PostBack, again Page_Load is called, but LoadViewState not, and MyProperty has null value.
Edit 2: I've debugged a little more (by comparing execution with Output Cache disabled) and found out that control postbacks (an asp:GridView's OnSelectedIndexChanging event) force the page to refresh by injecting a window.location=window.location; JavaScript in the page. But with cache enabled, gridview's event is executed only in the first postback, but not in the second one, preventing the page (and, subsequently, the control) to be reloaded to complete its task. But it's not the only problem, because of the property stored in ViewState.
I have a question, and it may be because I'm not understanding the way viewstate works. I have some code that sets a viewstate variable in the setter for a property in a custom control I have made.
public bool EditMode
{
get { return (bool)(ViewState["editMode" + this.ID] ?? false); }
set {ViewState["editMode" + this.ID] = value;}
}
The editmode is being set during a button click event.
public void shippingButton_Click(object sender, EventArgs e)
{
if (((Button)sender).CommandName== "Edit")
{
ctrlShippingAddress.EditMode = true;
}
else
{
Page.Validate();
if (Page.IsValid)
{
ctrlShippingAddress.SaveAddress();
ctrlShippingAddress.EditMode = false;
}
}
}
I've tried manually setting it on page load in case I wasn't adding this to the viewstate at the correct point in the page cycle, but as I understand it events occur before render. I have also tried adding ViewStateMode="Enabled" to the control, then to the page using it, then to the master page with no luck.
If I debug at the point of the get/set I see that viewstate is an empty collection (which doesn't make sense because it's also saving form data that is persisting as it should).
I appreciate any help.
You don't need to append the control ID to the ViewState key. I assume you're doing that for uniqueness, but it's not necessary.
The above may fix your problem, but if not try something like this instead:
public bool EditMode
{
get
{
bool editMode = false;
if (ViewState["editMode"] != null)
editMode = (bool)ViewState["editMode"];
return editMode;
}
set
{
ViewState["editMode"] = value;
}
}
After reviewing with a co-worker I discovered that the issue was in the pages node of the web.config
<pages enableViewState="false">
needed to be set to true
I created a user control. It contains one textbox. can I control this from parent web page.
Add the following property to your user control:
public string SomeValue
{
get
{
return txtSample.Text;
}
set
{
txtSample.Text = value;
}
}
And if you want to get or set the user control's textbox value from the page that contains the user control, just do the following:
MyUserControl.SomeValue = "Hello from page";
lblTest.Text = MyUserControl.SomeValue;
Where "MyUserControl" is the ID of the user control in the containing page.
Note: Since the TextBox control handles its Text property in the ViewState on its own, you don't have to explicitly handle it for this property.
Just define some public method or property in the user control and you can access it successfully. For example:
In UserControl1.ascx.cs:
public void DoSomething()
{
//Do something here from UserControl
}
In the parent:
MyInstanceOfUserControl1.DoSomething();
I need the following functionality in my method: if the method is called before OnLoad event of ASP.NET life cycle throw an exception else continue execution of the method.
I was thinking of something like this:
if (Page.LifeCycleState < LifeCycleState.OnLoad) {
throw new InvalidPageStateException();
}
Is it possible to retrieve the state of ASP.NET page life cycle?
One approach would be to use a Basepage that you always use in your site. This would contain a variable called PageLoadComplete, which you would set at the end of your PageLoad event. Then you could check the state of this variable from within your method.
public abstract class BasePage : System.Web.UI.Page
{
public bool PageLoadComplete { get; private set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
PageLoadComplete = true;
}
}
If you want to access the variable from code external to your page such as a UserControl, you would have to make it public and cast your page as BasePage.
public partial class MyUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
BasePage basePage = this.Page as BasePage;
if (basePage != null && !basePage.PageLoadComplete)
{
throw new InvalidPageStateException();
}
}
}
There is property in a realization of System.Web.UI.Control class(realization):
internal ControlState ControlState {
get { return _controlState; }
set { _controlState = value; }
}
Where ControlState is enum that contains members such as: Initialized, ViewStateLoaded, Loaded etc. here declaration
But as you can see this property is internal. So only way to get control state is proposed by Daniel Dyson.
You maybe able to find what you are looking for, by looking at the CurrentHandler and PreviousHandler properties of the current HttpContext.
if the method is called before OnLoad event of ASP.NET life cycle
throw an exception else continue execution of the method.
It is not clear which Onload event is meant, nor where the "method" resides. Is it the Page's Onload or a Control's OnLoad? Is it a Page's "method" or a Control's "method"?
Anyway, one can store sort of flag in the Context.Items Dictionary, which all controls (including Page) have access to during a request. This eliminates the need to use a general base page like suggested obove.
In the OnLoad method (no matter whether it is a Page's OnLoad or a Control's OnLoad):
Context.Items[UniqueID] = this;
In the "method":
if (Context.Items[UniqueID] != null)
{
throw new InvalidPageStateException();
}
In some book I've seen that they save custom properties of user control like this:
private int id = 0;
public int ID
{
get { return id; }
set { id = value; }
}
protected void Page_Init(object sender, EventArgs e)
{
this.Page.RegisterRequiresControlState(this);
}
protected override void LoadControlState(object savedState)
{
object[] ctlState = (object[])savedState;
base.LoadControlState(ctlState[0]);
this.ID = (int)ctlState[1];
}
protected override object SaveControlState()
{
object[] ctlState = new object[2];
ctlState[0] = base.SaveControlState();
ctlState[1] = this.ID;
return ctlState;
}
My question is why can I simply store it (in setter) in viewstate like: Vistate["ID"]=id;
and then retrieve it form there?
There is a difference between ViewState (what you are talking about in your question) and ControlState (what is shown in the sample code):
ViewState can be turned off by the user of your UserControl, by setting EnableViewState="false". In that case, you wouldn't be able to restore your property's value during the next request/postback (because there is no ViewState).
ControlState cannot be turned off. This means, that whatever you store in ControlState will be available during the next postback and you should therefore use ControlState for data that you absolutely need to be able to retrieve during the next request/postback.
See also these pages in MSDN: ASP.NET ViewState Overview and ControlState vs. ViewState
Excerpt from the first page:
In addition to view state, ASP.NET
supports control state. The page uses
control state to persist control
information that must be retained
between postbacks, even if view state
is disabled for the page or for a
control. Like view state, control
state is stored in one or more hidden
fields.