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);
}
}
Related
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
}
}
I have a ascx page suppose page1.ascx in that I have a button click event handler
btnSave.Click +=
delegate
{
if (Save != null) Save(this, EventArgs.Empty);
};
and I have another ascx page suppose page2.ascx in that I have a button click
protected void btnEdit_Click(object sender, EventArgs e)
{
// want to call
btnSave.Click +=delegate
{
if (Save != null) Save(this, EventArgs.Empty);
};
}
I want to call btnSave click delegate(page1.ascx) on btnEdit(page2.ascx). Is it possible if yes then how?
If I understood what you mean, one way would be as below:
public class Control1 : UserControl {
public delegate void ButtonClickHandler(object sender, EventArgs e);
public ButtonClickHandler ButtonClickEvent {get;set;}
public void Save(object sender, EventArgs e) {
//do something
if (ButtonClickEvent != null) {ButtonClickEvent(sender, e);}
//do something
}
}
public class Control2 : UserControl {
protected override void OnLoad(EventArgs e) {
control1.ButtonClickEvent += YourMethod;
}
protected void YourMethod(object sender, EventArgs e) { // do something here ... }
}
Another way is to declare your button's event in the first control as property and assign your method in the 2nd control.
I'd recommend moving the code out of the code-behind and into a separate class, so that it is accessible to both .ascx files.
I'm trying to subscribe to the the save button event of a user control that is launched in a separate radwindow from the calling parent. but I am getting object not initialized error, I know why but what am I missing?
Update: I found my error but it appears that if (this.SaveEvent!= null) in the ControlBase is always null
Parent Control Code:
public partial class myControl : ControlBase
{
private myChildControl __myChildControl;
private void myControl_PreRender(object sender, EventArgs e)
{
// error occurs here
//this.__myChildControl.SaveEvent += new myChildControl.SaveEventHandler(__myChildControl_SaveEvent);
// found my error
this.SaveEvent += new myChildControl.SaveEventHandler(__myChildControl_SaveEvent);
}
private void __myChildControl _SaveEvent(object sender, CustomEventArgs e)
{
this.Label1.Text = e.CustomEventArg1.ToString();
this.Label2.Text = e.CustomEventArg2.ToString();
}
}
Child Control Launched in RadWindow:
public partial class myChildControl : ControlBase
{
protected void btnSave_OnClick(object sender, EventArgs e)
{
CustomEventArgs _cea = new CustomEventArgs {CustomEventArg1 = 123, CustomEventArg2 = 12};
callBaseMethod(_cea);
}
}
ControlBase Code:
public class ControlBase : UserControl
{
public event CustomEventHandler SaveEvent;
public delegate void CustomEventHandler(object sender, CustomEventArgs e);
internal void callBaseMethod(CustomEventArgs cea)
{
if (this.SaveEvent!= null)
{
this.SaveEvent(this, cea);
}
}
}
CustomEventArgs class:
public class CustomEventArgs : EventArgs
{
public int CustomEventArgs1 { get; set; }
public int CustomEventArgs2 { get; set; }
}
This isn't possible in codebehind: the RadWindow presents a separate aspx/ascx page altogether that is linked to the main page through javascript alone.
What you need to do is handle the RadWindow OnClientClose event in javascript, then fire something in the parent page that performs the appropriate tasks.
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
}
}
A simple scenario: a custom class that raises an event. I wish to consume this event inside a form and react to it.
How do I do that?
Note that the form and custom class are separate classes.
public class EventThrower
{
public delegate void EventHandler(object sender, EventArgs args) ;
public event EventHandler ThrowEvent = delegate{};
public void SomethingHappened() => ThrowEvent(this, new EventArgs());
}
public class EventSubscriber
{
private EventThrower _Thrower;
public EventSubscriber()
{
_Thrower = new EventThrower();
// using lambda expression..could use method like other answers on here
_Thrower.ThrowEvent += (sender, args) => { DoSomething(); };
}
private void DoSomething()
{
// Handle event.....
}
}
Inside your form:
private void SubscribeToEvent(OtherClass theInstance) => theInstance.SomeEvent += this.MyEventHandler;
private void MyEventHandler(object sender, EventArgs args)
{
// Do something on the event
}
You just subscribe to the event on the other class the same way you would to an event in your form. The three important things to remember:
You need to make sure your method (event handler) has the appropriate declaration to match up with the delegate type of the event on the other class.
The event on the other class needs to be visible to you (ie: public or internal).
Subscribe on a valid instance of the class, not the class itself.
Assuming your event is handled by EventHandler, this code works:
protected void Page_Load(object sender, EventArgs e)
{
var myObj = new MyClass();
myObj.MyEvent += new EventHandler(this.HandleCustomEvent);
}
private void HandleCustomEvent(object sender, EventArgs e)
{
// handle the event
}
If your "custom event" requires some other signature to handle, you'll need to use that one instead.