You can adjust the appearance of your web form with a CSS (cascading style sheet). In the format menu of the VS.NET web form designer is
document styles. Here you select a css file or you can build a style on the spot. The (link to the) style will be embedded in the header of the webform. Take this example :
<HTML>
<HEAD>
<title>BaseForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
<LINK href="../StyleSheetMOC.css" type="text/css" rel="stylesheet">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
To give all the forms in your app the same appearance it would make sense to set the stylesheet in the base webform class of your app. The actual webforms inherit from this baseform and should inherit the stylesheet as well. Alas, this does not work. When inheriting from a webform you do not inherit the HTML in the header. And what is worse, it is next to impossible to influence the content of the header of a page being rendered.
The good thing is that the link to the stylesheet does not have to be in the header. Googling around I found several solutions. One of them was to start the response with the link. Which worked until the page contained a validator control. The other one was to finish the response with a link. This worked and I posted the first version of this post.
In a response on that Ryan Greg pointed to the importance of the place in the document where the link should be injected. To influence the injection place I used the Controls.AddAt() method in a second version to insert a literal control containing the link. The first parameter of this method is the desired location of the control in the the tree of the page. Passing a 0 inserts the link as first line of the response. That line is reserved for the doctype. If your page has a validator control, the script of that control will fail to load. Passing in a 1 inserts the link as first markup in the body.
But there is a big drawback to using the Controls.AddAt() method. It might (will allways ?) ruin the viewstate of the page, making the baseform pretty unusable. As an alternative I used the RegisterClientScriptBlock method in my third attempt. This method will insert any script, or a link to a style sheet, in the top of the rendered page before the rendered controls. Which is a nice location.
The link to the style sheet is in the web.config and read from the AppSettings. This location is the location as seen by the browser, something like
<add key="StyleSheet" value ="http://yourhost/su/moc/StyleSheetMOC.css"></add>
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
RegisterClientScriptBlock("MyCSS", string.Format("<link rel='stylesheet' type='text/css' href='{0}'></link>"));
}
As a result every page which inherits from the baseform contains a link to the stylesheet, its controls can successfully use the styles defined, and the viewstate of the pages keeps running as well.
Blog on, Peter