Integrating Master Pages + Content Pages + a Little AJAX
Getting your content and master pages to work side-by-side is easy, thanks to UpdatePanel.
Sometimes you need to have code in your content page update controls in your master page. It's not hard to do and, thanks to the default behavior of the UpdatePanel, getting it to work in AJAX is a snap.
Master pages provide you with an easy-to-use mechanism for ensuring that all your pages have the same structure. Master pages also handle content common to all pages by ensuring the same thing appears in the same place on every page. Problems arise, however, when that "same thing" changes from one page to another -- that is, when you have page-specific content for every page which you still want to appear on the same place on every page.
As an example, assume that you want a label that displays a page title on every page. To have this page title appear in the same place on every page, you'll put the label control on your master page. Unfortunately, the text that's being displayed is controlled by the content page because only code in the page can provide a "business-friendly/human-readable" title.
The simplest way to implement this is to think of your master page as an object that you can extend with new members. For instance, after dropping a label to display the page title onto the master page, you can add this code to the master page's code file to update that label:
Public Property PageTitle() As String
Set(ByVal value As String)
Me.PageTitleLabel.Text = value
After doing a recompile, in any of your content pages you'll be able to use this new property. First, in the code file for a content page, retrieve a reference to the master page through the page's master property. Your new property won't appear in the IntelliSense list for the master page until you cast the master property to the type of your master page:
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim mym As MyMaster
mym = CType(Me.Master, MyMaster)
mym.PageTitle = "Sales Information"
If you're using properties on your master page frequently on your site, constantly writing this code will get very boring. You can simplify the code by adding a MasterType directive that references the master page in the content page's source view:
<%@ MasterType TypeName="MyMaster" %>
Now, from the content page's code you can access the members you added to the master without having to do a cast (again, after doing a recompile):
Me.Master.PageTitle = "Sales Information"
Let's go to a more complicated problem. Let's say that your content page is busy adding items to the user's shopping cart and you want to display the status of the user's shopping cart on each page. You'll want to put that shopping cart status display in the same place on every page but the changes to the shopping cart will be made by the content page.
If you're not using AJAX, you can use the solution I've already described: As the user adds items to the shopping card, the entire page will postback to the server, giving you a chance to update the master page property. But you've gone one step further and put all of the content page's control inside an UpdatePanel. As a result, only changes to the portion of the page inside the content page's UpdatePanel will be displayed.
The answer is: Use the solution I described previously, but put the shopping cart status control into an UpdatePanel also (I'm assuming that you've put a ScriptManager control on your site's master page so that it's available on every page.) Whenever the UpdatePanel in the content page is refreshed, the UpdatePanel on the master page will also be refreshed so -- provided you update the status value in your server-side code -- the new status value will be displayed.
This behavior is the result of two features. First, the default behavior for ASP.NET is to refresh all UpdatePanels on the page if any one of them is refreshed. Second, all of the UpdatePanel processing happens on the client, inside the browser. Once your page gets down to the browser, it's all just HTML. There are no ASP.NET master pages, no content pages, no user controls -- the browser just sees a single page of HTML. So, from the page's point of view, there isn't an UpdatePanel on the master page and an UpdatePanel on the content page: There's just two UpdatePanels and they'll be refreshed together.
See? Sometimes, a new feature actually makes your life simpler.
About the Author
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.