2

简要问题*

通过一个或多个嵌套母版页在顶级母版页中引发事件时,您是否需要在嵌套母版页中捕获该事件并重新引发它?如果没有,采取什么更好的方法?

* 这是我希望在 SO.SE 上回答的问题 - 其余的只是为了提供更多背景信息来帮助解释它。

详细的问题,带有示例

母版页中的事件(我们称之为“TopLevel.master”)需要通过所有嵌套的母版页(假设只有一个并称之为“MidLevel.master”)触发到页面本身(Page.aspx)。我正在做的事情(如下)工作正常,但我担心我使用了错误的方法,这最终会在未来的某个时候咬住我例如,当我来维护代码时) . 这也可能是一种成本更高的方法,因为在可能不需要的地方创建了几个额外的事件。

每个嵌套母版页和页面本身都有一个@MasterType 声明,因此母版页的公共属性、方法和事件可通过后面的代码获得。

到目前为止,我有一些类似(为简洁起见)的内容:

顶级大师:

' A public event available from this master page
Public Event MyEvent(sender As Object, e As EventArgs)

' A function that can be called via "Master.DoSomething" to initiate the process
Public Sub DoSomething(someArgs As Object)
    Me._DoSomething(someArgs)
End Sub

' A local function that starts the process. SomeEventFiringObject is
' just an object that fires an event when the process is complete.
Private Sub _DoSomething(someArgs As Object)
    _someEventFiringObject.DoSomething(someArgs)
End Sub

' A local function that handles the process-complete event fired by
' SomeEventFiringObject and fires my public masterpage event
Private Sub Me_HandleEvent(sender As Object, e As EventArgs) Handles _someEventFiringObject.HasDoneSomething
    RaiseEvent MyEvent(sender, e)
End Sub

中级大师:

' Handle the event from the masterpage.
Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
    AddHandler Master.MyEvent, AddressOf Master_MyEvent
End Sub

' A public event available from this master page 
' NOTE: This is essentially the same event as in the TopLevel master page.
Public Event MyEvent(sender As Object, e As EventArgs)

' A function that can be called via "Master.DoSomething" to initiate the process
' NOTE: Just passing this up to the TopLevel master page.
Public Sub DoSomething(someArgs As Object)
    Master.DoSomething(someArgs)
End Sub

' A local function that re-raises the event from this master page
' NOTE: Handler added on Page.Init.
Private Sub Master_MyEvent(sender As Object, e As EventArgs)
    RaiseEvent MyEvent(sender, e)
End Sub

页面.aspx:

' EDIT: This needs to be done on Page.Init as well.
Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
    AddHandler Master.MyEvent, AddressOf Master_MyEvent
End Sub

' Some process initiation (button click in this example could be anything)
' The master page does the deed and will eventually raise the MyEvent event.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Master.DoSomething(someArgs)
End Sub

' The page handles the master MyEvent event (which is actually from MidLevel.master)
Private Sub Master_MyEvent(sender As Object, e As EventArgs)
    ' Finally I can do something with this event
End Sub

问题:

在我看来,必须有某种方法可以访问在 TopLevel 母版页中触发的 MyEvent 事件,而不必在 MidLevel 母版页中有效地捕获它,然后创建一个新事件并将其复制以发送它,但我可以' t 似乎解决了。有没有办法做到这一点?还是我采取的方法足够有效?

我担心的是,我实际上在 MidLevel.master 中有两层母版页,因此似乎有很多复制的代码和几个事件被创建,除了传递事件之外似乎没有其他原因。

4

1 回答 1

3

好的,您需要的第一个是创建描述母版页常用功能的界面。像这样的东西:

public interface IMaster
{
    event EventHandler MyEvent;
}

从该接口继承的 in top master page 定义您的事件:

private static readonly object MyEventObject = new object();

public event EventHandler MyEvent
{
    add
    {
        Events.AddHandler(MyEventObject, value);
    }
    remove
    {
        Events.RemoveHandler(MyEventObject, value);
    }
}

private void RaiseMyEvent()
{
    var handler = Events[MyEventObject] as EventHandler;
    if (handler != null)
    {
        handler(this, EventArgs.Empty);
    }
}

然后在嵌套母版页中定义事件,但将其添加到调用列表中委托给父级

public event EventHandler MyEvent
{
    add
    {
        ((IMaster)Master).MyEvent += value;
    }
    remove
    {
        ((IMaster)Master).MyEvent -= value;
    }
}

完成所有这些步骤后,您可以在页面上使用此事件:

protected void Page_Init(object sender, EventArgs e)
{
    ((IMaster)Master).MyEvent += new EventHandler(WebForm3_MyEvent);
}

VB.NET版无接口

顶级大师:

<asp:Button runat="server" Text="Click Me" OnClick="FireMyEvent" />

Private ReadOnly MyEventObject As Object = New Object()

Public Custom Event MyEvent As EventHandler
    AddHandler(value As EventHandler)
        Events.AddHandler(MyEventObject, value)
    End AddHandler

    RemoveHandler(value As EventHandler)
        Events.RemoveHandler(MyEventObject, value)
    End RemoveHandler

    RaiseEvent(sender As Object, e As System.EventArgs)
        Dim handler As EventHandler = TryCast(Events.Item(MyEventObject), EventHandler)
        If Not handler Is Nothing Then
            handler(Me, EventArgs.Empty)
        End If
    End RaiseEvent
End Event

Protected Sub FireMyEvent(sender As Object, e As EventArgs)
    RaiseEvent MyEvent(Me, EventArgs.Empty)
End Sub

嵌套大师:

Public Custom Event MyEvent As EventHandler
    AddHandler(value As EventHandler)
        AddHandler DirectCast(Master, TopMaster).MyEvent, value
    End AddHandler

    RemoveHandler(value As EventHandler)
        RemoveHandler DirectCast(Master, TopMaster).MyEvent, value
    End RemoveHandler

    RaiseEvent(sender As Object, e As System.EventArgs)
    End RaiseEvent
End Event

内容页

Protected Sub Page_Load(sender As Object, e As EventArgs)
    AddHandler DirectCast(Master, MasterPage2).MyEvent, AddressOf Foobar

End Sub

Private Sub Foobar(sender As Object, e As EventArgs)
    Response.Write("MyEvent handled from top master page at " & DateTime.Now.ToLongTimeString())
End Sub
于 2012-08-20T12:20:00.790 回答