ASP.NET 2.0 introduces a new concept called “data source”
controls – which are control objects that provide a standard way to expose data
that UI controls can then bind against. The data source model is extensible,
so you can easily build your own Data Source controls to plug into the system (this blog
post points to how to-do this). One of the built-in data-source controls
that ASP.NET 2.0 ships with is the <asp:sitemapdatasource> control –
which makes it super easy to databind any UI controls against the Site
Navigation data model.
ASP.NET 2.0 ships with built-in <asp:treeview> and
<asp:menu> controls, which can be used to create menu and tree-view
structures based on the site-map structure. To add and then data-bind the
<asp:menu> control to a <asp:sitemapdatasource> control on a page,
I could simple add this markup to the Site.Master file (replacing the previous
to-do menu comment):
Listing 5
<div id="navigation">
<asp:Menu ID="foo" DataSourceID="SiteMapDataSource1" runat="server">
</asp:Menu>
<asp:SiteMapDataSource ID="SiteMapDataSource1" ShowStartingNode="false" runat="server" />
</div>
I would then have a fly-out menu for navigating around the
site.
Alternatively, if I want even greater control over the HTML
generated, I could use more basic (but also more flexible) controls – like the
ASP.NET Repeater control.
For example, I could use the <asp:repeater> to create
an html <ul></ul> list like so:
Listing 6
<div id="navigation">
<ul>
<li>
<ahref="default.aspx">Home</a>
</li>
<asp:Repeater ID="foo" DataSourceID="SiteMapDataSource1" runat="server">
<ItemTemplate>
<li>
<a href='<%#Eval("url")%>'><%#Eval("Title")%></a>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</div>
<asp:SiteMapDataSource ID="SiteMapDataSource1" ShowStartingNode="false"runat="server" />
With our Web.SiteMap file defined like it is above, this
would then generate the below html at runtime:
Listing 7
<div id="navigation">
<ul>
<li>
<a href="default.aspx">Home</a>
</li>
<li>
<a href=
'/DALWalkthrough/Samples_Basic/BasicSamples.aspx'>Basic Data Samples</a>
</li>
<li>
<a href=
'/DALWalkthrough/Samples_Advanced/AdvancedSamples.aspx'>Advanced Data Samples</a>
</li>
<li>
<a href='/DALWalkthrough/About.aspx'>About</a>
</li>
</ul>
</div>
If I wanted to show the next level of hierarchy in the
SiteMap as well, I could add another <asp:repeater> within the first one
to also generate a sub-hierarchy of <ul><li><ul> elements.
For example:
Listing 8
<asp:Repeater ID="foo" DataSourceID="SiteMapDataSource1" runat="server" enableviewstate="false">
<ItemTemplate>
<li>
<a href='<%#Eval("url")%>'><%#Eval("Title")%></a>
<ul>
<asp:Repeater ID="bar"
DataSource='<%#Container.DataItem.ChildNodes()%>' runat="server">
<ItemTemplate>
<li><a href='<%#Eval("url")%>'><%#Eval("Title")%></a></li>
</ItemTemplate>
</asp:Repeater>
</ul>
</li>
</ItemTemplate>
</asp:Repeater>
Note that VB allows me to write
Container.DataItem.ChildNodes() as a direct data-bound expression. In C# I
would need to cast like so: ((SiteMapNode) Container.DataItem).ChildNodes()
This would then generate the below HTML markup:
Listing 9
<div id="navigation">
<ul>
<li><a href="default.aspx">Home</a></li>
<li><a href='/DALWalkthrough/Samples_Basic/BasicSamples.aspx'>Basic DataSamples</a>
<ul>
<li><a href='/DALWalkthrough/Samples_Basic/Sample1.aspx'>Samples 1</a></li>
<li><a href='/DALWalkthrough/Samples_Basic/Sample2.aspx'>Samples 1</a></li>
<li><a href='/DALWalkthrough/Samples_Basic/Sample3.aspx'>Samples 1</a></li>
<li><a href='/DALWalkthrough/Samples_Basic/Sample4.aspx'>Samples 1</a></li>
</ul>
</li>
<li><a href='/DALWalkthrough/Samples_Advanced/AdvancedSamples.aspx'>Advanced Data Samples</a>
<ul>
<li><a href='/DALWalkthrough/Samples_Advanced/Sample1.aspx'>Samples 1</a></li>
<li><a href='/DALWalkthrough/Samples_Advanced/Sample2.aspx'>Samples 1</a></li>
<li><a href='/DALWalkthrough/Samples_Advanced/Sample3.aspx'>Samples 1</a></li>
<li><a href='/DALWalkthrough/Samples_Advanced/Sample4.aspx'>Samples 1</a></li>
</ul>
</li>
<li><a href='/DALWalkthrough/About.aspx'>About</a>
</li>
</ul>
</div>
I can then use a standard CSS styling approach to customize
the look and feel of this structure however I want. Rachel Andrew has a great book that I
use called “The
CSS Anthology: 101 Essential Tips, Tricks & Hacks” that provides a
really nice scenario based tutorial approach to using CSS. I used a technique
she came up with in chapter 4 to make the markup above look like this when I
add some CSS to my StyleSheet.css file:
Figure 10
And now I have a nice looking menu for my site, data-bound
to the Site Navigation system, which is in turn data-driven from my web.sitemap
file.