Now if that title isn't a mouthful, I don't know what is. Anyways, this is something mostly for my benefit because I conveniently forget about this little trick and then have to go rooting through my code to remember and I'd rather have Google index it for me. =)
So I have this nifty little status message user control in the master page of my current project. It basically leverages a repeater to show a list of status messages with icons next to them based upon the type/severity. The idea is to have a method in the master page that takes a message and type as an argument and adds the message to an internal list which binds before render when all the processing is complete.
The problem is, I want to call to the user control from a user control in a page, so I have to jump two levels "up the chain" so to speak. Now, I hate FindControl() so I want it to be strongly typed to, so here is the solution I came up with.
Create a base page for the master page
Create a class, inherit it from master page, expose a virtual method which in my case writes a message. In this base page, I'm just dumping the message out in response.write since there's no user control here necessarily to handle it. MessageType is just an Enum I created with types like Success, Warning, Error, etc.
public class BaseMasterPage : MasterPage
{
public virtual void WriteMessage(string Message, MessageType Type)
{
Response.Write(Message);
}
}
Inherit your master page with the control from the BaseMasterPage and override the virtual method
The beauty of this is that I now have a common interface across my master pages for accepting messages from pages and user controls. They can all handle the messages in their own way. In the case of the following master page, I get a strongly typed call to my status message control (as I said before, it binds in the PreRender since it will have collected all the messages by then):
public partial class MyMasterPage : BaseMasterPage
{
protected void Page_PreRender(object sender, EventArgs e)
{
StatusViewer1.BindStatuses();
}
public override void WriteMessage(string Message, MessageType Type)
{
StatusViewer1.AddStatusItem(new StatusItem(Type, Message));
}
}
Internally, the viewer just as a List<StatusItem> of which status item is just a barebones object for the strongly typed generic (I love those damn generics).
In the case of a user control on a page, you just have to ensure that the master page being called is of type BaseMasterPage, and then pass the message out accordingly. Here's a snippet from one of my user controls:
if (Page.Master is BaseMasterPage)
{
((BaseMasterPage)Page.Master).WriteMessage("Some warning message.", MessageType.WARNING);
}
else
throw new Exception("You're supposed to inherit from BaseMasterPage, Doofus.");
Anyways, the point is that inheriting from your own custom base classes lends you a lot of extra firepower when it comes to dealing with pages and master pages and .net 2.0. Creating a BaseMasterPage and BasePage are two of the first things I do in about any project.