Some of my views lend themselves to a multi column format. For example, I have a search page with the criteria in a small side bar on the left and the search results in the main content area that takes up the rest of the screen. Not a problem right? You might start with a layout that looks like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>My Layout</title>
</head>
<body>
<div id="outer">
<div id="header">
</div>
<div id="content">
${ChildContent}
</div>
<div id="footer">
</div>
</div>
</body>
</html>
For your views that have two columns you would then have something like so:
<div id="sidebarContent">
...
</div>
<div id="mainContent">
...
</div>
Nothing revolutionary there. A few problems though. Any view that has two columns will have duplicated code for the sidebarContent element. What if you want to have some sort of static content in your sidebar? Like ads, dashboard info, who's logged in, etc? Usually you would add this stuff to your layout. But if you move the sidebarContent element to your layout, how do you then put dynamic view content in there? And how do you optionally disable the sidebar? One way to do it is to refactor your layout into something like so:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>My Layout</title>
</head>
<body>
<div id="outer">
<div id="header">
</div>
<div id="content">
<% if IsDefined("sidebarTemplate"): %>
<div id="sidebarContent">
<% OutputSubView(sidebarTemplate) %>
</div>
<% end %>
<div id="mainContent">
${ChildContent}
</div>
</div>
<div id="footer">
</div>
</div>
</body>
</html>
Things are getting interesting. We have added code to your layout to see if the PropertyBag contains an item named 'sidebarTemplate'. We expect 'sidebarTemplate', if present, to contain the path to a separate view that contains the dynamic sidebar content for the current view. We could also add any static sidebar content within the element. Your controller is now in...control...whether or not a sidebar should be displayed.
namespace My.App
{
using System;
using Castle.MonoRail.Framework;
public class ControllerBase : Controller
{
protected string SidebarTemplate
{
get { return PropertyBag["sidebarTemplate"] as string; }
set
{
if (value == null)
{
PropertyBag.Remove("sidebarTemplate");
}
else
{
PropertyBag["sidebarTemplate"] = value;
}
}
}
}
public class SearchController : ControllerBase
{
public virtual void Index()
{
SidebarTemplate = "search/indexSidebar";
}
}
}
Accessing search/index.rails would render search/indexSidebar.brail to the sidebarContent element and search/index.brail to the mainContent element.
This could easily be extended for multi-column layouts and give you the ability to put your dynamic view content in any well known areas of your page.
posted @ Friday, November 16, 2007 7:03 AM