I want to be able to execute something before the actual OnClick event is called upon a Button. I tried:
public class U_Button : Bunifu.Framework.UI.BunifuThinButton2
{
protected override void OnClick(EventArgs e)
{
MessageBox.Show("Click");
base.OnClick(e);
}
}
but the Messagebox is never shown. Any ideas why it doesn't work or how i can accomplish what i want to do? Because i want to avoid to write a check at the beginning of every OnClick event of a U_Button, so i thought i could somehow override it.
Thanks in advance!
Related
I am trying to understand for which purpose the events pattern decided that the method that fires the event should be declared virtual.
From C#6 in a Nutshell, from Joseph and Ben Albahari, O'Reilley:
Finally, the pattern requires that you write a protected virtual method that fires the
event. The name must match the name of the event, prefixed with the word On, and
then accept a single EventArgs argument:
Below a snippet I created to try to investigate.
I had the impression that the idea was to allow inheriting classes to completely overwrite how the event is handled, out of the box (original class). But the snippet below shows this is not possible, because deriving classes will never be able to invoke the event objects themselves (by the one one of the goals of the constraints imposed by the keyword event on delegates). The event can be invoked only in the containing class.
Now, since the pattern also asks that the method that fires the event simply check if the the event is not null and then call the delegate, with whatever every subscriber asked to do, what is left to be achieved by having the method that fires the event as virtual ? Inheriting classes are obliged to invoke the event the way it is in the broadcaster class, so all that is left for them is to add functionality. But this is exactly what they can achieve by subscribing to the event, in other words, by adding a call to an external function the time the event is fired.
I hope my wording is clear enough.
namespace eventsPatternVirtualEventFirerer
{
internal class Program
{
private static void Main(string[] args)
{
var obj = new X();
obj.ev += Obj_ev;
obj.Start();
}
private static void Obj_ev(object sender, EventArgs e)
{
Console.WriteLine("subscriber code...");
}
}
public class X
{
public event EventHandler<EventArgs> ev;
protected virtual void OnEvent(EventArgs e)
{
Console.WriteLine("original implementation...");
ev?.Invoke(this, e);
}
public void Start()
{
OnEvent(EventArgs.Empty);
}
}
public class X2 : X
{
public X2()
{
}
protected override void OnEvent(EventArgs e)
{
Console.WriteLine("inheriting class implementation overwrite...");
//compilation error - "the event 'X.ev' can only appear on the left hand side of += or -= (except when used from within the type 'X')"
ev?.Invoke(this, e);
}
}
}
I think the purpose is to allow derived classes to do something before/after the event is fired
public class X2 : X
{
public X2()
{
}
protected override void OnEvent(EventArgs e)
{
// Do something before the event
base.OnEvent(e);
// Do something after the event
}
}
There are a few things you can add/change in a derived class
Add a OnBeforeEvent / OnAfterEvent addition.
Choose not to broadcast the event (by conditionally not calling base.OnEvent(e)).
Vary the event args in some way.
Additionally, If you think about the way something like a page model works, it typically fires a Load event to notify when the page is loaded. Without a protected OnLoad method, derived classes would have to subscribe to it's own Load event to perform some action on load
public class MyPage : Page
{
protected override void OnLoad(EventArgs e)
{
// do something when the page is loaded
base.OnLoad(e);
}
}
versus:
public class MyPage : Page
{
public MyPage() : base()
{
this.Load += (sender,e) => {
// bleugh - subscribing to my own events
}
}
}
A good example might be the Paint event in Windows Forms.
// in MyButton : BaseButton : Control
void override OnPaint(object s, PaintEveargs e)
{
base.OnPaint(s, e); // Control: Draw background, BaseButton: draw border
// draw my own stuff
}
A button has several layers of base class, each drawing on top of each other.
I have a control which has an Event handler. I normally used this control on many pages where I manage the raised event. But now, just once I need to put this control into another control and subsequently on a page. Is there a way to trespassing the event from the original control?
Normal situation
Control1 > Page
Control1
public event EventHandler MyEvent;
protected virtual void OnMyEvent(EventArgs e)
{
if(this.MyEvent != null) this.MyEvent(this, e);
}
Page.aspx
<ASP:Control1 id="ctrl1" runat="server" OnMyEvent="ctrl1_MyEvent" />
Page.aspx.cs
protected void ctrl1_MyEvent(object sender, EventArgs e)
{
....
}
Exceptional case
Control1 > Control2 > Page
How can I do to re-raise the event to be managed on the page as described above? Is it possible?
I was planning to declare again on the second control an event handler and then create a method that raise the event, but I was thinking if there is another way to do this.
I'd suggest creating your own class, which I would call 'SomeNameEventManager'.
In your parent control, you directly subscribe / unsubscribe via this class.
And in your child control, you can raise the event by calling the method (e.g. OnChanged).
Example code:
public class SomeNameEventManager
{
ChangedEventHandler(object sender, EventArgs e);
public static event ChangedEventHandler Changed;
public static void OnChanged(EventArgs e) { Changed(this, e); }
}
Maybe you come up with a more dynamic way to do this.
In any case I guess, the way to go is to have a class in the middle.
I am trying to fire the Button Click event without clicking the actual button. Is there a way to invoke that? I want to call the Cancel event and here is what I have so far:
protected void Cancel(object sender, EventArgs e)
{
this.BindGridView();
}
Since all you have is this.BindGridView(), which I am assuming is just another method, you can just call that instead.
However, if you wanted to do more than just that, what I usually do is create methods for all my events in the form of OnXxx and call that from the event handler.
So for your example, you would create an OnCancel method:
private void OnCancel()
{
this.BindGridView();
}
... and then in your event handler:
protected void Cancel(object sender, EventArgs e)
{
this.OnCancel();
}
Doing this allows your event to trigger naturally and still function as well as allowing you the ability to call the same thing from anywhere within your code via this.OnCancel().
You can call the cancel method directly from within the same object:
Cancel(null,null)
Server side I've done it like this:
private void Page_Load(object sender, EventArgs e)
{
//Do something
Cancel(sender, e);
}
Is it the wrong way I am doing this:
- first I created a class inheriting from Combobox and I am gonna override some events, so something like this:
public override void SelectedIndexChanged(object sender, EventArgs e)
but it tells me : "There is no suitable method for override"
Thanks
You should override the method OnSelectedIndexChanged instead. The On[EventName] methods are the ones that raises the events. What you should do is to override that method, do the extra things you want to do and then call base.OnSelectedIndexChanged(e) when you want to raise the event:
protected override void OnSelectedIndexChanged(EventArgs e)
{
// do extra stuff here
base.OnSelectedIndexChanged(e);
// perhaps you want to do something after the event
// handlers have been invoked as well
}
You cannot override events. Instead you will find a method called OnSelectedIndexChanged, override this.
If I have a DropDownList control that makes up part of a CompositeControl how can I expose the SelectedIndexChanged event to the consuming aspx page?
Thanks
There is a much simpler way that is a direct pass through.
Try this:
public event EventHandler SelectedIndexChanged
{
add { this.TargetControl.SelectedIndexChanged += value; }
remove { this.TargetControl.SelectedIndexChanged -= value; }
}
[Edit] Unless of course you need to inject custom logic.
Here's what you do. First declare an event like this:
public event EventHandler SelectedIndexChanged;
Then, internally, hook up to the DropDownList's SelectedIndexChangedEvent. In your event handler do something like this:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.SelectedIndexChanged != null)
{
this.SelectedIndexChanged(sender, e);
}
}
All you're really doing is wrapping the original event and re-raising it.
EDIT: See Brian Rudolph's answer. That's in fact a much simple way of doing it.