Question in Brief*
When raising an event in a top level master page through one or more nested master pages, do you need to catch the event in the nested master page(s) and re-raise it? If not, what is the better approach to take?
* This is the question I’m hoping to have answered on SO.SE – the rest is just for more background information to help explain it.
Detailed Question, with Examples
An event in a masterpage (let’s call it “TopLevel.master”) needs to fire through all nested master pages (let’s assume there’s just one and call it “MidLevel.master”) to the page itself (Page.aspx). What I’m doing (below) works fine, but I’m concerned that I’m using the wrong approach and this will end up biting me in the derriere at some point in the future (e.g. when I come to maintain the code). It may also be a more costly approach, as several additional events are being created where they may not be needed.
Each nested master page and the page itself has a @MasterType declaration, so public properties, methods and events of the master pages are available via the code behind.
So far, I have something along the lines of (simplified for brevity):
TopLevel.master:
' 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
Page.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
The Question:
It seems to me that there must be some way to access the MyEvent event fired in the TopLevel master page without having to effectively catch it in the MidLevel master page, then create a new event and copy it to send it on, but I can’t seem to work it out. Is there a way to do this? Or is the approach I’ve taken valid enough?
My concern is that I actually have two layers of master pages within MidLevel.master, so there seems to be a lot of copied code and several events being created for seemingly no reason other than to pass the event on.
Ok, the first that you need is to create interface describing common functionality of your master pages. Something like this:
The in top master page inherited from this interface define your event:
Then define event in nested master page but delegate adding it to invocation list to parent
After all these steps you may use this event on page:
VB.NET version without interface
Top Master:
Nested master:
Content page