单个ASP.NET UserControl事件的多个订阅者?

时间:2011-10-04 14:11:04

标签: asp.net user-controls asp.net-4.0

我对我页面上的事件管道问题感到困惑。我有一个ASP.NET UserControl,它监视一些浏览器端事件,并将它们作为UpdatePanel async-post-backs引发到服务器。我们称之为EventPump。它包括一些用于管理事件的JavaScript和服务器端控件。它很棒。

我在同一页面上有几个其他控件,彼此不了解但想订阅EventPump引发的一些事件。通常,一个控件将通过在其标记中包含该控件并对事件进行布线来订阅另一个事件。但是在这种情况下会给我多个EventPump实例,这是我不想要的。

如何让几个UserControl订阅公共EventPump控件的事件?

3 个答案:

答案 0 :(得分:1)

我能想到的一些其他选择:

  1. 接口代码,因此EventPump控件实现了具有各种公共事件的IEventPump。包含页面使用一个名为EventPump的属性实现IEventPumpContainer,该属性允许所有其他用户控件进行如下注册:

    ((IEventPumpContainer)Page).EventPump.MyEvent += MyEventHandler;
    
  2. 如果页面知道需要订阅的控件,您可以在事件触发时调用控件上的相应方法。例如:

    EventPump.MyEvent += (s, e) => SomeControl.SomeMethod();
    
  3. 另外,可以说更好的是使事件成为一等公民,并拥有一个可用于订阅和提升事件的事件调度程序。例如:

    Events.Register<MyEvent>(e => TextBox.Text = "MyEvent Happened");
    ...
    Events.Raise(new MyEvent());
    

答案 1 :(得分:0)

在用户控件中创建事件处理程序,并将所有事件订阅到页面上的同一个处理程序。

的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);
}    

页:

<uc:UserControl1 ID="UserControl1" runat="server" SomethingChanged="UserControl_Changed" ... />
<uc:UserControl2 ID="UserControl2" runat="server" SomethingElseChanged="UserControl_Changed" ... />

代码隐藏:

protected void UserControl_Changed(object sender, EventArgs e)
{
    Label1.Text = "Stuff has changed...";
}

修改

有关跨用户控件调用事件的信息,请参阅此文章:

http://www.codeproject.com/KB/aspnet/EventsAcrossUCs.aspx

答案 2 :(得分:0)

有两种选择:

  1. 将EventPump放在母版页上并创建一个引用它的属性(通过@MasterType指令使主页“强类型化”)

  2. 添加一个静态帮助器方法,该方法将Page实例作为参数,并在页面上查找EventPump实例。您可以在Page.Items中简单地注册控件,而不是使用FindControl,这在大页面上会很慢。此方法最好与EventPump控件中的代码结合使用,以确保页面上只存在一个EventPump实例。

  3. 以ScriptManagerProxy的样式创建一个EventPumpProxy控件。这有点笨拙,但如果您更喜欢在本地使用声明性标记而不是大量代码隐藏,这很好。我不知道确切的实现细节,但你应该能够通过反汇编AJAX框架源来看到它们。