2

簡単な質問*

1 つ以上のネストされたマスター ページを介してトップ レベルのマスター ページでイベントを発生させる場合、ネストされたマスター ページでイベントをキャッチして再発生させる必要がありますか? そうでない場合、より良いアプローチは何ですか?

* これは、私が SO.SE で回答したいと思っている質問です。残りは、それを説明するための背景情報です。

詳細な質問と例

マスターページ ("TopLevel.master" と呼びます) のイベントは、ネストされたすべてのマスター ページ (1 つしかないと仮定して、"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

MidLevel.master:

' 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

質問:

MidLevel マスター ページで効果的にキャッチせずに TopLevel マスター ページで発生した MyEvent イベントにアクセスし、新しいイベントを作成してコピーして送信する方法が必要だと私には思えますが、できます。うまくいかないようです。これを行う方法はありますか?それとも、私が取ったアプローチは十分に有効ですか?

私の懸念は、MidLevel.master 内に実際には 2 層のマスター ページがあるため、多くのコピーされたコードといくつかのイベントが、イベントを渡す以外の理由で作成されているように見えることです。

4

1 に答える 1

3

まず、マスター ページの共通機能を記述するインターフェイスを作成する必要があります。このようなもの:

public interface IMaster
{
    event EventHandler MyEvent;
}

このインターフェイスから継承された上部のマスター ページは、イベントを定義します。

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 に答える