I am working with a Web Form in ASP.NET and I want to understand that why can I omit the parameter in override Event Handler?
This is Event :
public event EventHandler Init;
This is Delegate to Hold Data(with two parameters) :
public delegate void EventHandler(object sender, EventArgs e);
Event Handler goes like :
protected override void OnInit(EventArgs e)
{
i++;
this.Load += Page_Load;
}
Adding parameter is not allowed in above method(handler) but at the same time we are restricted to pass parameter in below case
protected void Page_Load(object sender, EventArgs e)
{
i++;
Response.Write(i);
}
Note : I have disabled my Auto Event Wire-Up attribute in Directive.
Actually you are not subscribing to Init event. AutoEventWireUp make sure Page_Init method is called when Init Event is fired.
As you have disable it, then you have to manually hook up the method like this
protected override void OnPreInit(EventArgs e)
{
Init += new EventHandler(OnInit);
base.OnPreInit(); // make sure you call this
}
Reason you will not get compile time error is because there are two types of EventHandler delegate
EventHandler(object,EvnetArgs)
EvnetHandler(EventArgs)
The difference is that Page_Load really is an event handler whereas OnInit is a method that is defined in the base class and raises the Init event. So in the case of your OnInit method, you are overriding the method and not defining an event handler.
If you want to create an event handler for the Init event, you would also have to create a method with the following signature:
protected void Page_Init(object Sender, EventArgs e)
{
// ...
}
This only works if AutoEventWireUp is set to true. Otherwise, you need to register event handlers in your ASPX page or the codebehind file. As the Init event is raised very in the page lifecycle, the event handler needs to be registered at the beginning of the request. In the special case of Init it is very common to override OnInit instead of defining an event handler. Important to note though, if you override OnInit (or one of the other On* methods) you should always call the base version in order to allow for the ASP.NET framework to do its stuff:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
// initialization code
}
Related
I want to execute a function on Page_load event of every System.Web.UI.Page from which derives my own CustomPage class (which obviously inherits from Page class as well)
what I have done so far it that I created CustomPage class like this:
public class CustomPage : System.Web.UI.Page
{
protected virtual void Page_Load(object sender, EventArgs e)
{
CallTOTheDesiredFunction(); //this is the call to the function I want
}
}
And in the derived Page classes I am doing this:
public class DerivedPage : CustomPage
{
protected override void Page_Load(object sender, EventArgs e)
{
base.Page_Load(sender, e);
//the rest of the page load event which executes from here on
}
}
As it is obvious, this approach is working but it is not the best solution since I have to call base.Page_Load(sender, e) on every derived page.
Is there a better solution to what I am trying to achieve?
Thank you in advance
Yes. It is better to override the Onload method rather than relying on deriving classes to call the base method.
You can still hook on the Load event in every page, but use the method in the base class.
public class CustomPage : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
CallTOTheDesiredFunction(); //this is the call to the function I want
base.OnLoad(e);
}
}
I am getting stumped with my plug-in architecture that I am trying to develop with respect to events. I can do this just fine, in a single application: (Obviously this is a very simplified version of what I am trying to accomplish, and if this were my code there are easier ways to accomplish this, just try to follow the logic ;)
public Form1()
{
public event EventHandler OnValueOver5Chars;
Main()
{
OnValueOver5Chars+= new EventHandler(WarnUser);
....
}
private void textBox_Changed( object sender, EventArgs e )
{
if( sender.Text.count() > 5 )
OnValueOver5Chars(sender, e); // WORKS HERE
}
private void WarnUser(object sender, EventArgs e)
{
...
}
}
However, now I have a plug-in architecture, where the plugin implements an interface which houses my event:
// Interface.cs
public interface IPlugin
{
event EventHandler OnValueOver5Chars;
...
}
// Plugin1.cs
public class Plugin1 : IPlugin
{
public event EventHandler OnValueOver5Chars;
Plugin1()
{
OnValueOver5Chars += new EventHandler(Plugin1WarnUser);
}
private void Plugin1WarnUser(object sender, EventArgs e)
{
...
}
}
// Form.cs
public class Form1 : Form
{
public Form1()
{
Assembly SampleAssembly = Assembly.LoadFrom("Plugin1.dll");
Type myType = SampleAssembly.GetTypes()[0];
if (myType.GetInterfaces().Contains(typeof(IPlugin)))
{
IPlugin myInstance = Activator.CreateInstance(myType) as IPlugin;
myInstance.OnValueOver5Chars(this, new EventArgs());
// Compiler Error CS0079 - The event 'event' can only appear on the left hand side of += or -=
}
}
????
You're trying to hook up an event to another event, and that won't work. You need to hook the plug-ins event to a method/delegate. Once you do that, have the method/delegate call the other event.
myInstance.OnValueOver5Chars += OnValueOver5CharsFunc;
...
/*In Form1*/
void OnValueOver5CharsFunc( object sender, EventArgs args )
{
OnValueOver5Chars( sender, args );
}
Events in C# have the property that they are not "callable" directly as methods (or as such as delegates) outside of the class where they are defined.
In your first example you are calling the event from within the class in which you define it. In the second example, however, you are trying to call OnValueOver5Chars from outside the class - hence the error.
To solve this you could consider adding a method to your IPlugin interface (e.g. ValueOver5Chars) that performs OnValueOver5Chars. Note that it is more common to name the event ValueOver5Chars (say), and provide a method OnValueOver5Chars to raise it (i.e. the other way round). See for example the Windows Forms Button class and its Click event.
I am regularly encountering errors of type "An unhandled exception of type 'System.StackOverflowException' occurred in Unknown Module.". This happens in a website with a quite large code base. But the error occurs only after several minutes of the website.
This is where the error pointed me to:
public partial class HealthInsurance : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
base.OnLoad(e);
Page.Header.DataBind();
}
}
You should not call the base class' implementation of OnLoad() from an autowired Page_Load() handler.
Under the hood, OnLoad() is responsible for invoking Page_Load(), so your code ends up in an infinite recursive loop.
You only have to write:
protected void Page_Load(object sender, EventArgs e)
{
Page.Header.DataBind();
}
Things would be different had you chosen to override OnLoad() rather than rely on Page_Load(). In that case, you indeed have to call the base class' method:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Page.Header.DataBind();
}
If you are subscribing to the Load event, do not call the base OnLoad as the base OnLoad is what's responsible for firing the Load event, so it will be an endless cycle.
However, if you are overriding the OnLoad method, then it's appropriate to call the base OnLoad method, e.g.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Page.Header.DataBind();
}
In the above case, note the override keyword.
I am able to hook the event and also allowed to override load and init.., events in my aspx codebehind file. I have following questions.
public partial class Default : System.Web.UI.Page
{
public Default()
{
this.Init += Default_Init;
this.Load+=Default_Load;
}
protected void Default_Load(object sender, EventArgs e)
{ }
protected void Default_Init(object sender, EventArgs e)
{ }
protected override void OnLoad(EventArgs e)
{ }
protected override void OnInit(EventArgs e)
{ }
}
Qs:
Why such option(both virtual method and event handler) is exist in Page class?
When override methods got executed, my event handlers(Default_Load and Default_Init) are not executed. what is the reason behind?
Should i call base.OnLoad(e); in overridden OnLoad method? Why should/shouldn't I?
By default, OnInit and OnLoad are not handlers of Init and Load events. They are used to Fire Init and Load events.
When you override, you change the behavior of these methods thus, events are not fired by OnInit and OnLoad methods (unless you explicitly write base.OnInit etc.)
If you change the behavior of OnLoad and do not call base method, then you may break the page lifecycle of asp.net application. For instance, Load event will not be called.
Normally, the method OnXxx raises the event named Xxx. This is also the case in a System.Web.UI.Control like Page.
If you do:
protected override void OnLoad(EventArgs e)
{
// nothing here!
}
you change the behavior of OnLoad so that it now does nothing. Therefore, most probably, no-one will ever raise ("fire") the Load event. So its event handler is never run.
If instead you do:
protected override void OnLoad(EventArgs e)
{
// maybe add some code of your own here ...
base.OnLoad(e);
// ... or here
}
then the base call will make sure the method still raises the event.
You can only raise the event explicitly, i.e. invoke the underlying delegate, if you're in the class where the event was declared. So that's not a possibility for you. The base class where Load is defined does that like this:
// inside same class where 'Load' event is defined:
protected virtual void OnLoad(EventArgs e)
{
// maybe they put some other code here ...
var loadDelegate = Load; // gets the current underlying delegate of the event
if (loadDelegate != null)
loadDelegate(this, e);
// ... or here
}
But in most situation you shouldn't override any method at all. Just add to Load when you want some code to run when the Load event fires.
I have WinForms application. My Form derived class has UserControl derived class.
I simply put several controls into one UserControl to simplify reuse. The Load event of UserControl is not fired. Do I have to set some property?
Try overriding the OnLoad() method in your UserControl. From MSDN:
The OnLoad method also allows derived
classes to handle the event without
attaching a delegate. This is the
preferred technique for handling the
event in a derived class.
protected override void OnLoad(EventArgs e)
{
//Your code to run on load goes here
// Call the base class OnLoad to ensure any delegate event handlers are still callled
base.OnLoad(e);
}
There wouldn't be any special properties you need to set for a UserControl's events to fire. You have one of 2 ways to subscribe to the event. In the Properties (property grid) select the events list...double-click at the Load property. All the necessary pieces of code will be put in place, and your cursor will be waiting for you at the proper method.
The second method is subscribing to the event like so:
public MyMainForm( )
{
InitializeComponents();
myUserControl.Load += new System.EventHandler(myUserControl_Load);
}
void myUserControl_Load(object sender, EventArgs e)
{
MessageBox.Show(((UserControl)sender).Name + " is loaded.");
}
One reason for the Load event to stop firing is when you have a parent of your control that does something like this
protected override void OnLoad(EventArgs e)
{
//do something
}
you always need to make sure to do this
protected override void OnLoad(EventArgs e)
{
//do something
base.OnLoad(e);
}