I have two controls.
class ControlA
{
public ControlA()
{
//some code
this.PreviewKeyDown += ControlA_PreviewKeyDown;
}
protected void ControlA_PreviewKeyDown(object sender, KeyEventArgs e)
{
// do A things
}
}
I also have a control B which inherits control A
class ControlB : ControlA
{
public ControlB()
{
//some code
this.PreviewKeyDown += ControlB_PreviewKeyDown;
}
protected void ControlB_PreviewKeyDown(object sender, KeyEventArgs e)
{
// do B things
}
}
when the PreviewKeyDown event is fired, both ControlB_ and ControlA_PreviewKeyDown are fired. But I want only ControlB_PreviewKeyDown is fired for a ControlB. Is that possible? If so, how to implement that?
Thank you so much.
Assuming you can change the code of both ControlA and ControlB here's a possible solution:
class ControlA
{
public ControlA(bool subscribe = true)
{
if (subscribe)
{
this.PreviewKeyDown += ControlA_PreviewKeyDown;
}
}
protected void ControlA_PreviewKeyDown(object sender, KeyEventArgs e)
{
// do A things
}
}
class ControlB : ControlA
{
public ControlB() : base(false)
{
//some code
this.PreviewKeyDown += ControlB_PreviewKeyDown;
}
protected void ControlB_PreviewKeyDown(object sender, KeyEventArgs e)
{
// do B things
}
}
your "problem" is due to the fact that ControlB class constructor calls also the ControlA constructor... you can create a ControlA(bool fromParent=true) which doesn't add the handler of this.PreviewKeyDown += ControlA_PreviewKeyDown;
HTH
Try setting e.Handled = true; in the ControlB handler, and in the ControlA handler, wrap the logic in an if(!e.Handled)
Or, since you have the ControlA handler as protected, you can unsubscribe from it in ControlB constructor:
this.PreviewKeyDown += ControlB_PreviewKeyDown;
In PreviewKeyDown we will check for sender type to determine from which control event fired.
Like
protected void ControlA_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (sender.GetType() == typeof(ControlA))
{
// do A things
}
}
protected void ControlB_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (sender.GetType() == typeof(ControlB))
{
// do A things
}
}
Related
I made a derived class from Button control class. When I use the control, I need to make to be prevented from invocation in some situation. The situation is already defined in the derived class, myClick function. I guessed there is a way like setting e.Cancel = true, but I can't. Can you give a simple suggestion to solve this task?
public class SButton : Button
{
public SButton() : base()
{
Click += new System.EventHandler(myClick);
}
private void myClick(object sender, EventArgs e)
{
if( meHandsome )
{
// here I want to prevent no more event invocation!
}
}
}
public partial class UTeachAdvanced : DevExpress.XtraEditors.XtraUserControl
{
private void UTeachAdvanced_Load(object sender, EventArgs e)
{
SButton btn = new SButton();
Controls.Add(btn);
btn.Click += new EventHandler(delegate(object sender, EventArgs args)
{
Console.Write("ugly");
}
}
}
The situation is already defined in the derived class.
The Click event raises by Control.OnClick method. To prevent raising Click event, you can override OnClick and call base.OnClick only if the criteria to prevent the click is not true:
public class SampleButton : Button
{
protected override void OnClick(EventArgs e)
{
if(!criteriaToPrevent)
base.OnClick(e);
}
}
Here is my code in my userControl
public partial class UserControlHomeScreen : UserControl
{
public event EventHandler SomethingHappened;
public void DoSomething()
{
EventHandler handler = SomethingHappened;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
public void HandleEvent(object sender, EventArgs args)
{
MessageBox.Show("Wafak.");
}
public UserControlHomeScreen()
{
InitializeComponent();
}
private void btnAverageDailyBal_Click(object sender, EventArgs e)
{
this.Tag = 0;
this.Hide();
}
private void btnComputeTransferPricing_Click(object sender, EventArgs e)
{
this.Tag = 1;
this.Hide();
}
}
And here is my code in my main form
private void HomeScreen()
{
uHomeScreen = new UserControlHomeScreen();
uHomeScreen.Dock = DockStyle.Fill;
//uHomeScreen.Disposed += new EventHandler(uHomeScreen_Disposed);
uHomeScreen.SomethingHappened += new EventHandler(uHomeScreen_SomethingHappened);
panelMain.Controls.Add(uHomeScreen);
}
void uHomeScreen_SomethingHappened(object sender, EventArgs e)
{
MessageBox.Show("throw new NotImplementedException();");
}
What i want to happen is that when the usercontrol is hidden i want to fire an event in my main form but does not work, what am i missing? please help. thanks!
Your naming convention for event raiser (DoSomething) is confusing, your code doesn't call DoSomething (or raise the event SomethingHappened), so how could it fire for you? Add the following code in your user control class:
//override the OnVisibleChanged
protected override void OnVisibleChanged(EventArgs e){
if(!Visible) DoSomething();
}
I've created a custom user control for a windows form that will operate similar to a button (and please don't suggest that I just use a button, because I will be storing data in this user control), but I can't figure out how to get the OnClick() event to fire. I've sifted through a handful of tutorials and looked at a few similar questions on the site, but I can't seem to get the event to fire off - so I'm either doing something wrong or everyone posted incorrect code (I hope it isn't the latter)
In my custom control.cs,
namespace MobCreator {
public partial class MOBSample : UserControl {
public MOBSample() {
InitializeComponent();
}
protected override void OnMouseUp(MouseEventArgs e) {
this.BorderStyle = BorderStyle.FixedSingle;
base.OnMouseUp(e);
}
protected override void OnMouseDown(MouseEventArgs e) {
this.BorderStyle = BorderStyle.Fixed3D;
base.OnMouseDown(e);
}
public event EventHandler ButtonClick;
private void OnButtonClick(object sender, EventArgs e) {
// invoke UserControl event here
if (this.ButtonClick != null) this.OnButtonClick(sender, e);
}
}
}
And in my form.cs,
private void MobCreatorForm_Load(object sender, EventArgs e) {
UserControl1.ButtonClick += new EventHandler(this.CustomEvent_Handler);
}
private void CustomEvent_Handler(object sender, EventArgs e) {
Console.WriteLine("Click");
}
However, when I run the program my console never outputs "Click".
Check this link on MSDN: it is a simple Event tutorial, you should be able to adapt it to your scenario.
At a first look, what you are probably missing is a Delegate for your event.
Try this
private void MobCreatorForm_Load(object sender, EventArgs e)
{
CustomEvent_Handler(null,null);
}
private void CustomEvent_Handler(object sender, EventArgs e)
{
Console.WriteLine("Click");
}
I have created a user control that contains a button.
I am using this control on my winform which will be loaded at run time after fetching data from database.
Now I need to remove a row from a datatable on the Click event of that button.
The problem is that how do I capture that event in my form. Currently it goes in that user control's btn click event defination.
You can create your own delegate event by doing the following within your user control:
public event UserControlClickHandler InnerButtonClick;
public delegate void UserControlClickHandler (object sender, EventArgs e);
You call the event from your handler using the following:
protected void YourButton_Click(object sender, EventArgs e)
{
if (this.InnerButtonClick != null)
{
this.InnerButtonClick(sender, e);
}
}
Then you can hook into the event using
UserControl.InnerButtonClick+= // Etc.
It's not necessary to declare a new delegate. In your user control:
public class MyControl : UserControl
{
public event EventHandler InnerButtonClick;
public MyControl()
{
InitializeComponent();
innerButton.Click += new EventHandler(innerButton_Click);
}
private void innerButton_Click(object sender, EventArgs e)
{
if (InnerButtonClick != null)
{
InnerButtonClick(this, e); // or possibly InnerButtonClick(innerButton, e); depending on what you want the sender to be
}
}
}
Just modernizing ChéDon's answer, here is how you can do it in 2018:
public class MyControl : UserControl
{
public event EventHandler InnerButtonClick;
public MyControl()
{
InitializeComponent();
innerButton.Click += innerButton_Click;
}
private void innerButton_Click(object sender, EventArgs e)
{
InnerButtonClick?.Invoke(this, e);
//or
InnerButtonClick?.Invoke(innerButton, e);
//depending on what you want the sender to be
}
}
VS2008, C#, .NET FRAMEWORK2.0
I want this: click button1, webbrowser1._DocumentCompleted() event revokes doA(); click button2, it revokes doB(); click button3, it revokes doC().
I know how to do it using JAVA and I guess C# has this mechanism too. Could anyone give me some idea or better, show me some example?
myButton.Click += myButton_Click;
protected void myButton_Click(object sender, EventArgs e) {}
To Add a handler
button.Click += buttonClickEventHandler;
To remove a handler
button.Click -= buttonClickEventHandler;
To add to these answers, you can also add an anonymous method to an event:
myButton.Click += (object sender, EventArgs e) => {
MessageBox.Show("MASSIVE ERROR!");
};
What this means is that you can effectively call a method even if it does not match the appropriate event handler signature:
myButton.Click += (object sender, EventArgs e) => {
DoA();
};
Or (without using a lamba expression):
myButton.Click += delegate(object sender, EventArgs e) {
DoA();
};
If you want to add event handlers to a control, which is what I think you are describing, you can easily do this. One common approach is to assign control event handlers in the code behind during page load:
protected void Page_Load(object sender, EventArgs e)
{
//add the event handler for the click event. You could provide other
//logic to determine dynamically if the handler should be added, etc.
btnButton1.Click += new EventHandler(btnButton1_Click);
btnButton2.Click += new EventHandler(btnButton2_Click);
btnButton3.Click += new EventHandler(btnButton3_Click);
}
protected void btnButton1_Click(object sender, EventArgs e)
{
//get the button, if you need to...
Button btnButton1 = (Button)sender;
//do some stuff...
DoA();
}
protected void btnButton2_Click(object sender, EventArgs e)
{
//do some stuff...
DoB();
}
protected void btnButton3_Click(object sender, EventArgs e)
{
//do some stuff...
DoC();
}
private void DoA() {}
private void DoB() {}
private void DoC() {}
Declaring an event
public class MyClass1
{
...
public event EventHandler<EventArgs> NotifyValidate;
protected void RaiseNotifyValidate(EventArgs e)
{
if (NotifyValidate != null)
{
NotifyValidate(this, e);
}
}
...
}
Firing that event in your code
...
RaiseNotifyValidate(new EventArgs()); //EventArgs could be more sophisticated, containing data etc..
Registering for that event in your code:
...
MyClass aObj = new MyClass();
aObj.NotifyValidate += new EventHandler(onNotifyValidate);
...
private void onNotifyValidate(object sender, EventArgs e)
{
//do what you need to
}
As Dan pointed out, with Lambda expressions you can define events like
aObj.NotifyValidate += (s,ev) =>
{
//handle your event
};