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.
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 customized control inside the splitview's pane. Now I have the method hideinternal() defined inside the control which makes the control invisible. However, at the same time I also want to close the pane. What should I do? (I know it is SplitView.IsPaneOpen = false; I don't know how to get access to it inside the control's code behind)
I would raise an event from within hideinternal that can then be subscribed to in your view where you could hide the Pane.
eg in your Custom Control the event
public event EventHandler CloseSplitViewPane;
public void OnCloseSplitPaneView(object sender, EventArgs e)
{
CloseSplitViewPane?.Invoke(sender, e);
}
in hideinternal
public void hideinternal()
{
OnCloseSplitViewPane(this, new EventArgs());
}
in your view for example MainPage.xaml.cs constructor (Your Custom Control is called MyControl in this example)
public MainPage()
{
this.InitializeComponent();
MyControl.CloseSplitViewPane += (sender, e) =>
{
SplitView.IsPaneOpen = false;
};
}
Hope that helps
I finally defined an event handler inside the control;
public event EventHandler handlesomething;
then in hideinternal I notify the event;
private void hideinternal()
{
doSomething();
this.NotifyEvent(handlesomething);
}
in the main page's XAML I sign the event handler to some events inside the page
<Control
handlesomething ="SomeMethodsInsideMainPage"
/>
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);
}
I created a custom control which is actually just two labels inside a panel. I want to add an event so that when my custom control is clicked (which would really be clicking either one of the labels) it would return the properties of the whole control, I think that would mean that 'sender' in the event handler would be my custom control and not one of the lables. I don't know if I made myself clear but what I mean is to treat the control as a 'whole' when it is clicked mmm anyway hope you get my point.
How can I do this?
Thanks in advance
What you can do is let the custom control consume the event of the label, and in the custom control implement a new event. Then, when the label event fires, you can fire your own event from the custom control.
For example:
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);
}
}
You can get the container object of your label and cast it to your custom control
private void Label1_Click(object sender, System.EventArgs e)
{
Box box = (object as Label).Parent as Box;
if(box != null)
{
//Do what you need here.
}
}
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.