Multiple subscribers to single ASP.NET UserControl event?
I am puzzling over an event plumbing problem on my page. I have a single ASP.NET UserControl that monitors some browser-side events and raises them as UpdatePanel async-post-backs to the server. Let's call it EventPump. It includes some JavaScript and server-side controls to manage the events. It works great.
I have several other controls on the same page that don't know about each other but would like to subscribe to so开发者_高级运维me of the events raised by the EventPump. Normally one control would subscribe to another's events by including that control in its markup and wiring the events. But in this case that would give me multiple instances of EventPump, which I don't want.
How can I have several UserControls subscribe to events of the common EventPump control?
A few additional options I can think of:
Code to interfaces, so the EventPump control implements IEventPump which has a various public events. The containing page implements IEventPumpContainer with one property called EventPump which allows all other user controls to register like so:
((IEventPumpContainer)Page).EventPump.MyEvent += MyEventHandler;
If the page is aware of the controls that need to subscribe you could have it call appropriate methods on the controls when events fire. For example:
EventPump.MyEvent += (s, e) => SomeControl.SomeMethod();
Alternatively and arguably better is to make the events first class citizens and have an event dispatcher that can be used to subscribe to and raise events. For example:
Events.Register<MyEvent>(e => TextBox.Text = "MyEvent Happened"); ... Events.Raise(new MyEvent());
A couple of options:
Put the EventPump on a master page and create a property that references it (by making the master page "strongly typed" through the @MasterType directive)
Add a static helper method that takes a Page instance as a parameter, and finds the EventPump instance on the page. Instead of using FindControl for this, which will be slow on large pages, you can simply register the control in Page.Items. This approach is best combined with code in the EventPump control that ensures that only one EventPump instance exists on the page.
Make an EventPumpProxy control in the style of ScriptManagerProxy. This is somewhat kludgy, but nice if you prefer to have declarative markup locally instead of a lot of code-behind. I don't know the exact implementation details, but you should be able to see them by disassembling AJAX framework sources.
Create event handlers in the user controls, and subscribe all of the events to the same handler on the page.
UserControl1:
public event EventHandler SomethingChanged;
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
//do OnSelectedIndexChanged logic
if (this.SomethingChanged != null)
this.SomethingChanged(this, e);
}
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
//do OnCheckedChanged logic
if (this.SomethingChanged != null)
this.SomethingChanged(this, e);
}
UserControl2:
public event EventHandler SomethingElseChanged;
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
//do OnTextChanged logic
if (this.SomethingElseChanged != null)
this.SomethingElseChanged(this, e);
}
protected void Button1_Click(object sender, EventArgs e)
{
//do OnClick logic
if (this.SomethingElseChanged != null)
this.SomethingElseChanged(this, e);
}
Page:
<uc:UserControl1 ID="UserControl1" runat="server" SomethingChanged="UserControl_Changed" ... />
<uc:UserControl2 ID="UserControl2" runat="server" SomethingElseChanged="UserControl_Changed" ... />
Code-behind:
protected void UserControl_Changed(object sender, EventArgs e)
{
Label1.Text = "Stuff has changed...";
}
EDIT
See this article for invoking events across user controls:
http://www.codeproject.com/KB/aspnet/EventsAcrossUCs.aspx
精彩评论