Creating Some Style
Denise Wynn
December 13, 2004
Download the example code for this article. CreatingStyleCode.zip
Up until now our template has been pretty lackluster on the style front. We're going to look at some different ways that you can apply styles to your user controls using the .Net Framework.
Style Properties of WebControl
By default System.Web.UI.WebControls.WebControl contains some style properties. The following properties are common although not every control supports every property:
BackColor
BorderColor
BorderStyle
BorderWidth
Font
ForeColor
Height
Width
Let's start by setting a border for the label controls that we use to display each item in our navbar control. Open the navbar.ascx file that was created for the previous article and add the following bold lines within the RenderLink method.
public void RenderLink(string Title, string Url)
{
Label s = new Label();
if(Url == contexturl)
{
//special case - we don't want to render the current
//pages nav item as a link
s.BorderColor = System.Drawing.Color.FromName("Red");
s.BorderStyle = BorderStyle.Solid;
s.BorderWidth = Unit.Pixel(2);
s.Controls.Add(new LiteralControl(Title));
}
else
{
HyperLink h = new HyperLink();
h.Text = Title;
h.NavigateUrl = Url;
s.BorderColor = System.Drawing.Color.FromName("Black");
s.BorderStyle = BorderStyle.Solid;
s.BorderWidth = Unit.Pixel(2);
s.Controls.Add(h);
}
NavBar.Controls.Add(s);
}
View full navbar.ascx code here.
As you can see adding a border to the label controls using the supplied properties is a bit cumbersome. You have to use three separate properties for a single border. You can't use strings to set those properties. For the BorderColor property you have to use a Color structure. The code adds a rather large style attribute to each span (label control) element that is rendered on the page. The opening span for one of our navbar items will be:
<span style="border-color:Black;border-width:2px;border-style:Solid;">
If you have a custom color that doesn't fall under one of the many defined colors within System.Drawing.Color you can use the FromArgb() method to create it. If you want to use a border color of #AD1731 you will first have to get its RGB equivalent. I used Photoshop to determine that the RGB equivalent for #AD1731 is 173, 23, 49 but you can find many hex to rgb converters and pages available on the web. Now we can use that information to create a custom color by using the System.Drawing.Color.FromArgb() method. To do this we would change our line where we set our BorderColor property to:
s.BorderColor = System.Drawing.Color.FromArgb(173, 23, 49); s.BorderStyle = BorderStyle.Solid; s.BorderWidth = Unit.Pixel(2);
That will give us the following output in our span.
<span style="border-color:#AD1731;border-width:2px;border-style:Solid;">
I know you're probably all saying that was way too much work just to render a border around a span. I don't disagree. On top of that you're probably wondering how you render other styles since the available styles are extremely limited. What do you do if you just want to set border-bottom or a margin or background-image?
The Style Property
Programmatically, if you want to do more with styles than what is provided by WebControl you can use the Style property. The Style property allows you to specify a style and its associated value. These will be added to the style attribute of the control.
If we wanted to add a little spacing between our navbar items using margin-left we could use the Style property to add that.
s.BorderColor = System.Drawing.Color.FromName("Black");
s.BorderStyle = BorderStyle.Solid;
s.BorderWidth = Unit.Pixel(2);
s.Style["margin-left"] = "3px";
In our span that is rendered from the label control the margin-left is appended to the end of the styles attribute.
<span style="border-color:Black;border-width:2px;border-style:Solid;margin-left:3px;">
We could even use the Style property to set a single border style that would replace the three styles already there.
s.Style["border"] = "solid 2px black"; s.Style["margin-left"] = "3px";
Now in our span element we have:
<span style="border:solid 2px Black;margin-left:3px;">
That is a definite improvement but it's still not great. We've condensed three lines of code down to one in our user control and we have about a third of the characters being output to the style element in each span tag but there is still a lot of bloat. What if you need to add eight different styles and their values? You'd have eight lines of code in your control and a long style element added to all the span elements in the navbar control. Eventually that's going to add up to a lot of extra characters. If you are concerned about the size of your html output this could significantly increase the file size if you are writing out several styles for every tag on your page.
The CssClass Property
That is where the CssClass property comes in. The CssClass property allows you to move all of your style logic to a css (Cascading Style Sheet) file and just specify the class that you want to add to your control.
In your test directory create a text file named template.css and add the following text to it.
body
{
background:#ffffff;
color:#666666;
font-family:verdana,arial,sans-serif;
font-size:small;
}
.navLink
{
border:solid 2px #000000;
padding-left:3px;
padding-right:3px;
}
.navLink a
{
text-decoration:none;
color:#000000;
}
.navCurrent
{
border:solid 2px #AD1731;
padding-left:3px;
padding-right:3px;
padding-bottom:3px;
color:#000000;
}
I'm not going to go into great detail about css in this article. If you are interested in learning more about Cascading Style Sheets and styles in general I suggest you check out this great CSS Tutorial at the W3 Schools site.
This style sheet contains a style block for the body tag to set some general properties for our page. We've also added two classes; navLink, which defines the styles for the navigation links in our navbar control and navCurrent, which defines some different styles for our currently selected item. The item ".navLink a" is a way of specifying styles for any "a" tags that are children of the tag that uses the navLink class.
Open the template.aspx page in your test directory for editing and add the following bold line.
<%@ Page runat="server" language="c#"%>
<%@ Register TagPrefix="nbs" TagName="banner" Src="banner.ascx" %>
<%@ Register TagPrefix="nbs" TagName="footer" Src="footer.ascx" %>
<%@ Register TagPrefix="nbs" TagName="navbar" Src="navbar.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>User Control Template</title>
<link rel="stylesheet" type="text/css" href="template.css" />
</head>
<body>
<nbs:banner runat="server" />
<nbs:navbar sourcexml="nav.xml" runat="server"/>
<p></p>
<nbs:footer runat="server" />
</body>
</html>
Now that we've referenced the css file in our template we can use the CssClass property. Open the navbar.ascx file for editing and replace the BorderColor, BorderStyle, and BorderWidth lines that where previously added with the following bold lines within the RenderLink method.
public void RenderLink(string Title, string Url)
{
Label s = new Label();
if(Url == contexturl)
{
//special case - we don't want to render the current
//pages nav item as a link
s.CssClass = "navCurrent";
s.Controls.Add(new LiteralControl(Title));
}
else
{
HyperLink h = new HyperLink();
h.Text = Title;
h.NavigateUrl = Url;
s.CssClass = "navLink";
s.Controls.Add(h);
}
NavBar.Controls.Add(s);
}
View full navbar.ascx code here.
Now when the navbar control is rendered in the page the span tags will be much shorter since they only contain a class attribute and value.
<span class="navLink">
Additionally since all of the styles are contained in a single css file instead of being written out individually for each span that reduces the bloat even further.
Here is how our style would look applied to a page.
It's a simple style for demonstration purposes but it does designate the currently selected item by using a different style than all the other navbar items. You can also see that the page is using a different font from the default browser font that it displayed before.
Putting it to work
As we did in the previous articles lets create some pages from our template so we can really see our style in action. In the test directory make a copy of template.aspx and call it firstpage.aspx. Open firstpage.aspx in a text editor and add the following bold line.
<%@ Page runat="server" language="c#"%>
<%@ Register TagPrefix="nbs" TagName="banner" Src="banner.ascx" %>
<%@ Register TagPrefix="nbs" TagName="footer" Src="footer.ascx" %>
<%@ Register TagPrefix="nbs" TagName="navbar" Src="navbar.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>User Control Template</title>
<link rel="stylesheet" type="text/css" href="template.css" />
</head>
<body>
<nbs:banner runat="server" />
<nbs:navbar sourcexml="nav.xml" runat="server"/>
<p>This is my first page with my new template.</p>
<nbs:footer runat="server" />
</body>
</html>
Make additional copies of template.aspx called default.aspx, secondpage.aspx, thirdpage.aspx, and fourthpage.aspx. Change the content in each page to make it unique.
We've added a couple pages since the last time so we'll need to add those to our xml file. Open the nav.xml file in the test directory and add the following bold lines.
<?xml version="1.0" encoding="utf-8" ?> <items> <item title="Home" url="/test/default.aspx" /> <item title="Template" url="/test/firstpage.aspx" /> <item title="First Page" url="/test/secondpage.aspx" /> <item title="Template" url="/test/thirdpage.aspx" /> <item title="First Page" url="/test/fourthpage.aspx" /> </items>
Now save everything and in your browser go to http://localhost/test/default.aspx. Click on each link in the navbar to see it all working.
In Conclusion
So now you've learned how to add some style to your user controls using the .Net Framework. While the method you use might be a matter of personal preference I personally think it's wise to consider factors such as total page weight and maintainability when making your choices.
