I've run into a weird problem while developing a control. I've registered a handler for Page.InitComplete event from the control, but the handler is not executed. I need the handler to be executed exactly on InitComplete event, because I depend on complex application architecture.
My code looks like this (This code is placed inside my control class):
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.Page.InitComplete += (sender, args) => OnInitComplete(args);
}
However OnInitComplete is never entered.
If it is somehow possible I would like to find the way to register my handler to Page.InitComplete event without using my own events & weird hacks.
Apart from that I'm curious about the reason of this behaviour.
I'm sorry - my fault. The problem was in custom PageBase class :
protected override void OnInitComplete(EventArgs e)
{
if (!String.IsNullOrEmpty(FormAction) && FormActionInitComplete != null)
{
FormActionInitComplete(FormActionSender, FormAction, FormActionValue);
}
}
The Page.OnInitComplete method is implemented in the following way :
protected virtual void OnInitComplete(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventInitComplete];
if (handler != null) {
handler(this, e);
}
}
and in the overriden method of the PageBase there was no call of the base.OnInitComplete method - that is why the event was not raised.
Related
I had an interview a week ago and one of the questions was what the difference between OnInit, Page_Init and PreRender. which one is preferable?
Page_Init is an event handler for the Page.Init event, you typically see it if you add a handler within the class itself.
OnInit is a method that raises the Init event.
The two can be seen as being equivalent if used within a subclass, but there is a difference: only Init is exposed to other types, the OnInit method is protected and is responsible for raising the event, so if you override OnInit and fail to call base.OnInit then the Init event won't be fired. Here's how it looks like:
public class Page {
public event EventHandler Init;
public event EventHandler Load;
protected virtual void OnInit(Object sender, EventArgs e) {
if( this.Init != null ) this.Init(sender, e);
}
protected virtual void OnLoad(Object sender, EventArgs e) {
if( this.Load != null ) this.Load(sender, e);
}
public void ExecutePageLifecylce() {
this.OnInit();
// do some houskeeping here
this.OnLoad();
// further housekeeping
this.Dispose();
}
}
public class MyPage : Page {
public MyPage() {
this.Init += new EventHandler( MyPage_Init );
}
private void MyPage_Init(Object sender, EventArgs e) {
// No additional calls are necessary here
}
protected override void OnLoad(Object sender, EventArgs e) {
// you must make this following call for any .Load event handlers to be called
base.OnLoad(sender, e);
}
}
Generally overriding the OnLoad / OnInit methods is faster (but this is a microptimisation, you're only saving a couple of extra instructions for delegate dispatch) and many "purists" will argue using events unnecessarily is just ugly :)
Another advantage of not using events is avoiding bugs caused by AutoEventWireUp which can cause events to be called twice for each page load, which obviously is not desirable if your event-handlers are not idempotent.
I have a Default.aspx page and I am using a usercontrol in it. On some condition in usercontrol.cs I have to invoke a function present in Default.aspx.cs page (i.e parent page of user control). Please help and tell me the way to do this task.
You have to cast the Page property to the actual type:
var def = this.Page as _Default;
if(def != null)
{
def.FunctionName();
}
the method must be public:
public partial class _Default : System.Web.UI.Page
{
public void FunctionName()
{
}
}
But note that this is not best-practise since you are hard-linking the UserControl with a Page. Normally one purpose of a UserControl is reusability. Not anymore here. The best way to communicate from a UserControl with it's page is using a custom event which can be handled by the page.
Mastering Page-UserControl Communication - event driven communication
Add an event to the user control:
public event EventHandler SpecialCondition;
Raise this event inside your user control when the condition is met:
private void RaiseSpecialCondition()
{
if (SpecialCondition != null) // If nobody subscribed to the event, it will be null.
SpecialCondition(this, EventArgs.Empty);
}
Then in your page containing the user control, listen for the event:
public partial class _Default : System.Web.UI.Page
{
public void Page_OnLoad(object sender, EventArgs e)
{
this.UserControl1.OnSpecialCondition += HandleSpecialCondition;
}
public void HandleSpecialCondition(object sender, EventArgs e)
{
// Your handler here.
}
}
You can change the EventArgs to something more useful to pass values around, if required.
parent.aspx.cs
public void DisplayMsg(string message)
{
if (message == "" || message == null) message = "Default Message";
Response.Write(message);
}
To Call function of parent Page from user control use the following:
UserControl.ascx.cs
this.Page.GetType().InvokeMember("DisplayMsg", System.Reflection.BindingFlags.InvokeMethod, null, this.Page, new object[] { "My Message" });
This works fine for me..
Try this
MyAspxClassName aspxobj= new MyUserControlClassName();
aspxobj.YourMethod(param);
I want to check Session in some pages. To do this I am adding the page names which I want to check inside web.config as a appsetting key.
I want to use httpHandler with firing an event after it finds the session is empty or something else.
If I create httpHandler as a dll(another project) and add to a web site, can handler fire an event and web site capture it inside a web page?
What you can do is this:
Your HttpHandler puts a value in the HttpContext.Current.Items collection telling if there was Session or not. Something like
HttpContext.Current.Items.Add("SessionWasThere") = true;
You create a BasePage that checks that value in the Page_Load event and raises a new event telling so:
public abstract class BasePage : Page {
public event EventHandler NoSession;
protected override void OnLoad(EventArgs e){
var sessionWasThere = (bool)HttpContext.Current.Items.Add("SessionWasThere");
if(!sessionWasThere && NoSession != null)
NoSession(this, EventArgs.Empty);
}
}
In your page, you suscribe to that event:
public class MyPage : BasePage{
protected override void OnInit(){
NoSession += Page_NoSession;
}
private void Page_NoSession(object sender, EventArgs e) {
//...
}
}
I have C# Web Application that has an aspx page hosting a user control (Review.ascx). Inside that user control there are 5 more user controls, one of which has a public event (Review_Summary.ascx). The problem is no matter what i do I cannot get the event wired up in the parent ascx control (Review.ascx).
Here is what I have in the child control (Review_Summary.ascx)
public event EventHandler forwardStatusChanged;
#region methods
protected void btnForward_Click(object sender, EventArgs e)
{
if (btnForward.Text == "Return")
{
if (forwardStatusChanged != null)
{
forwardStatusChanged(sender, e);
}
removeForward();
}
}
In the parent control (Review.ascx) I have this
public void initReview(string EmployeeNumber)
{
RevSummary.forwardStatusChanged += new EventHandler(RevSummary_forwardStatusChanged);
<more code here>
}
protected void RevSummary_forwardStatusChanged(object sender, EventArgs e)
{
lblReadOnly.Visible = false;
}
RevSummary is the ID of the child control in the parent control. InitReveiw is a method that is called by the aspx page in its Page_Load event.
I get no errors on compile or at runtime. But when I click the button the forwardStatusChanged event is null. The "removeForward()" method that is called after that executes properly. So that fact that the event is always null leads me to believe that the wire up in the parent control is not working. However, I am sure it is executing becasue all of the code after that executes.
How can I figure out why this event is not wiring up?
Where is initReview being called from? Are you sure it's being called because the only reason this happens is that the event handler wasn't truly setup. I've never found a reason other than this, the several times I did this myself.
HTH.
Let's say I have a base page class with a Page_load() event handler and I also have a Page_load() event handler in the derived page class. I realised you don't have to wrote vitual or override keyword and compiler does not detect error. Why is this? And why is is base class version executed?
Those are just events.
To override, you need to use the OnLoad method available on Control.
Try overriding the event firing method and call your own. I can't explain why it's not complaining about both but I know they are added to the event, and hence are both in the queue to be executed.
protected override void OnLoad(EventArgs e)
{
this.Page_Load(this, e);
}
The method you are overriding here doesn't do anything fancy except execute all event handlers in the queue. See the snippet from Reflector below:
protected internal virtual void OnLoad(EventArgs e)
{
if (this.HasEvents())
{
EventHandler handler = this._occasionalFields.Events[EventLoad] as EventHandler;
if (handler != null)
{
handler(this, e);
}
}
}
I was wrong. There was indeed a warning about shadowing a parent class method, but it was just a warning, not an error.