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.
Related
Imagine I have a class (form / window) that has a button. In my class I subscribe the button to a method and I throw my own event in it:
public delegate void MyEventHandler(object source, MyEventArgs e);
public event MyEventHandler MyEvent;
protected virtual void OnMyEvent(MyEventArgs e)
{
if (this.MyEvent != null) this.MyEvent(this, e);
}
private void Button_Click(object sender, EventArgs e)
{
this.OnMyEvent(???, ???);
}
What is the correct way to trigger my event. Should I use this with my own EventArgs?
this.OnMyEvent(this, new EventArgs());
Or should I send my sender and event arguments down to the subscription of my own event?
this.OnMyEvent(sender, e);
What is the correct way. Should we stick to one method only? How is Microsoft doing it? Any code guidelines?
Thank you.
Think about who will be subscribing to your event. Will they need to know if it came from a button? Or will they only need to know that it was fired?
Personally I would prefer the listener to only know the event was triggered and the sender is my class which gives me the freedom to change who can fire the event in the first place e.g. button click, timer etc.
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 have UserControl which has two components
public System.Windows.Forms.ComboBox innerComboBox;
public System.Windows.Forms.TextBox innerTextBox;
and when i am using this UserControl i can not call Validating event like
myName.Validation += new System.ComponentModel.CancelEventHandler(myName_Validating);
becouse not working. I must call it like.
myName.innerTextBox.Validating += new System.ComponentModel.CancelEventHandler(myName_Validating);
can i override my UserControll that all events will be calling from innerTextBox of TextBox ?
In your UserControl, try adding it like this:
public new event CancelEventHandler Validating {
add { innerTextBox.Validating += value; }
remove { innerTextBox.Validating -= value; }
}
Then your myName.Validating should work like you want.
No, but you can "wrap" them in some ways, meaning you will need to expose the events from your top-level user control to which outsiders can subscribe, and then, subscribing to the inner-control even handlers, "inform" your top-level subscribers. For instance...
public class MyControl
{
public event CancelEventHandler Validating;
public System.Windows.Forms.TextBox innerTextBox;
public MyControl()
{
//post-instantiation stuff here
innerTextBox.Validating += myName_Validating;
}
void myName_Validating(oject sender, CancelEventArgs e)
{
if (Validating != null)
{
Validating(sender, e);
}
}
}
How exactly you want to wrap them is up to you; if you want your control to have some handling logic prior to publishing and executing the top-level subscriptions (can be handy in threading situations) then this will work, otherwise a more concise and practical approach for your might be what LarsTech suggests.
I have a control which extends UserControl. This control contains two ComboBox controls. I've created an event handler which fires when either of the combos changes:
public event EventHandler ComboChanged
{
add { cmbA.SelectedIndexChanged += value; cmbB.SelectedIndexChanged += value; }
remove {...}
}
When I add an event handler to this event, is there any way for the sender to be reported as the custom control (i.e. the ComboBox's parent control) rather than the ComboBox itself? Or am I trying to do something I shouldn't be doing here?
You should have something like this :
public event EventHandler MyControlChanged
and then in your userControl two functions for each of the ComboBox
protected void oncmbA_SelectedIndexChanged(object sender, EventArgs e)
{
if (MyControlChanged!=null)
MyControlChanged(this, e);//or some new Eventagrs that you wish to communicate
}
protected void oncmbB_SelectedIndexChanged(object sender, EventArgs e)
{
if (MyControlChanged!=null)
MyControlChanged(this, e);//or some new Eventagrs that you wish to communicate
}
this would then refer to the UserControl and not to the combobox that fired your UserControl's event.
Yoann's answer is the way to go. Here's a similar pattern, but with some minor differences.
// Default listener makes null-check unnecessary when raising event.
// Note that no custom implementations are provided for add, remove.
public event EventHandler ComboChanged = delegate { };
...
foreach(var comboxBox in new[] {cmbA, cmbA})
{
// Attach listener to combo-box's event that raises our own event.
// Lambda-expression is ok since we don't intend to ever unsubscribe.
comboBox.SelectedIndexChanged += (sender, args) => ComboChanged(this, args);
}
Someone gave me this code that works great. But I would really like to understand what is happening inside it. Could somebody explain please? What is the meaning of each part of the code? The code is inside a custom control which has two labels inside a panel.
Also I've seen some custom control events that use add/remove syntax, what is that for? What is the difference with what is happening here?
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public event EventHandler MyCustomClickEvent;
protected virtual void OnMyCustomClickEvent(EventArgs e)
{
// Here, you use the "this" so it's your own control. You can also
// customize the EventArgs to pass something you'd like.
if (MyCustomClickEvent != null)
MyCustomClickEvent(this, e);
}
private void label1_Click(object sender, EventArgs e)
{
OnMyCustomClickEvent(EventArgs.Empty);
}
}
See my comments below. Also for a more detailed event I blogged on this concept a while back where I go into more detail on the entire process.
public partial class UserControl1 : UserControl
{
//This is the standard constructor of a user control
public UserControl1()
{
InitializeComponent();
}
//This defines an event called "MyCustomClickEvent", which is a generic
//event handler. (EventHander is a delegate definition that defines the contract
//of what information will be shared by the event. In this case a single parameter
//of an EventArgs object.
public event EventHandler MyCustomClickEvent;
//This method is used to raise the event, when the event should be raised,
//this method will check to see if there are any subscribers, if there are,
//it raises the event
protected virtual void OnMyCustomClickEvent(EventArgs e)
{
// Here, you use the "this" so it's your own control. You can also
// customize the EventArgs to pass something you'd like.
if (MyCustomClickEvent != null)
MyCustomClickEvent(this, e);
}
private void label1_Click(object sender, EventArgs e)
{
OnMyCustomClickEvent(EventArgs.Empty);
}
}
I'd recommend reading up on Events for C# on MSDN. This is covered in detail.
Basically, MyCustomClickEvent is an event. The OnMyCustomClickEvent method is used to raise the event, but is being done in a way that subclasses can also raise this event if required.
When you click on "label1", the OnMyCustomClickEvent method runs, which raises the event. Any delegates subscribed to the event will execute at that point.
You mentioned seeing the add/remove syntax for events in some custom control examples. Most likely those examples are using the UserControl class' Events property to store event handlers, such as in the following example:
public event EventHandler MyEvent
{
add
{
Events.AddHandler("MyEvent", value);
}
remove
{
Events.RemoveHandler("MyEvent", value);
}
}
The idea there is that usually a consumer of a control is not going to want to handle every single event that the control exposes. If each event is defined as a "field" event (as in your example), then each event will take up a chunk of memory even if there are no subscribers for that event. When you have a complex page constructed of hundreds of controls, each of which may have dozens of events, the memory consumption for unused events is not insignificant.
This is why the System.ComponentModel.Component class (the base class of the System.Windows.Forms.Control class) has an Events property, which is basically a dictionary to store event handler delegates. This way each event is implemented more like a property than a field. The add/remove handlers for each event store or remove delegates from the Events dictionary. If an event is not used, then there just isn't an entry in the Events dictionary for it, and no additional memory is consumed for that event. It's a trade-off of doing slightly more work (having to look up the event handler) to save slightly more memory.
EDIT: fixed my answer to pertain to Windows Forms, rather than ASP.NET, although the concepts are the same.
Concerning the add/remove, this is a "manual" implementation of events. The following two snippets do the same thing.
Automatic implementation:
public event EventHandler MyEvent;
Manual implementation:
private EventHandler _myEvent;
public event EventHandler MyEvent
{
add { _myEvent += value; }
remove { _myEvent -= value; }
}
This is exactly the same idea as automatic properties where:
public string Property { get; set; };
Does exactly the same as:
private string _property;
public string Property
{
get { return _property; }
set { _property = value; }
}
The difference between these snippets is that with the manual implementations, you get more control. Examples are:
Implement logic in the add/get and remove/set;
Get access to the fields which allows you to set e.g. [NonSerializable];
Put the values in e.g. a Dictionary.
The Form class e.g. does the latter to keep the number of fields in the Form class down.