About

I'm Mike Pope. I live in the Seattle area. I've been a technical writer and editor for over 30 years. I'm interested in software, language, music, movies, books, motorcycles, travel, and ... well, lots of stuff.

Read more ...

Blog Search


(Supports AND)

Google Ads

Feed

Subscribe to the RSS feed for this blog.

See this post for info on full versus truncated feeds.

Quote

People think that you have these things called ideas and that writing is a matter of imposing them on the subject material, whereas it's only in the writing that I discover what it is that I think.

Anthony Lane



Navigation





<October 2014>
SMTWTFS
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

Categories

  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  
  RSS  

Contact

Email me

Blog Statistics

Dates
First entry - 6/27/2003
Most recent entry - 10/16/2014

Totals
Posts - 2312
Comments - 2502
Hits - 1,674,969

Averages
Entries/day - 0.56
Comments/entry - 1.08
Hits/day - 405

Updated every 30 minutes. Last: 4:00 PM Pacific


  06:01 PM

On the forums, someone was asking about creating a horizontal menu using Razor code in ASP.NET Web Pages. The technique of combining an unordered list (<ul> element) with CSS to create a horizontal layout, using <a> elements as the menu items, is a pretty well-known one; you can find examples here and here, not to mention in the Site.css file that comes with a lot of the Visual Studio web project templates.

The actual Razor part is likewise not hard. Someone showed this code as a way to dynamically build a list (to which you'd then apply the CSS):

<ul>
@foreach (var item in collection)
{
<li>@item</li>
}
</ul>
The interesting part was a comment that the original poster made:
It sounds like if I have lots of logic inside the loop, I might be best served moving that to the back end somewhere and just calling a method that returns the text to display within each list item.
What this sounded like to me was a fun excuse to see about creating a custom helper. Helpers are, in effect, chunks of code and markup; when you invoke the helper, it runs the code and emits the markup. For example, by creating a helper to render a horizontal menu, you could do something like this in a page:

@MyHelpers.HorizontalMenu(
"Home|Default.cshtml",
"About|About.cshtml",
"Login|Login.cshtml",
"Register|Register.cshtml")
<h1>My Page</h1>
<p>Hello, horizontal menu.</p>
And get something like this:

Well, anyway, in the App_Code folder of an ASP.NET Web Pages site (it must be in that folder), I created a file named MyHelpers.cshtml. In the new file I replaced the default contents with the following:

@helper HorizontalMenu(params string[] menuListArray) {

string[] menuItem;
string menulink = "";
string menuLIitems = "";

<style>
/* This should all be in a .css somewhere */
#horizontalMenu{height:28px;background-color:lightgray;
font-family:"Segoe UI";font-size:11pt;font-weight:bold;
color:white;}
#horizontalMenu ul {margin:0px; padding:0px;}
#horizontalMenu ul li{
display:inline;height:30px;float:left;list-style:none;
margin-left:15px;position:relative;
border-right:2px solid white;padding:6px;
}
#horizontalMenu li a {color:#fff; text-decoration:none;}
#horizontalMenu li a:hover {color:red;}
</style>

<div id="horizontalMenu">
@for(int i = 0; i < menuListArray.Length; i++){
menulink = "";
if(menuListArray[i].Contains("|")){
menuItem = menuListArray[i].Split( new Char[]{'|'});
menulink =
String.Format("<a href=\"{1}\">{0}</a>",
menuItem[0],
menuItem[1]);
}
else{
menulink = menuListArray[i];
}
menuLIitems += "<li>" + menulink + "</li>";
}
<ul>@Html.Raw(menuLIitems)</ul>
</div>
}

Update 7 Feb 2012 Fixed a typo in the code (I'd named the variable menuListArrary instead of menuListArray). I'd used the misspelled variable name consistently, so everything worked ok, but I corrected the name anyway to avoid potential confusion.

Some things of note, I guess:
  • The name of the file (MyHelpers.cshtml) acts as the namespace for any helpers in that file; the name of the helper itself (first list of the previous example) is the method. That's why the earlier example invokes the helper as MyHelpers.HorizontalMenu.

  • The CSS for the menu layout probably should not be in this file; it probably should be in a separate .css file.

  • And/or at least parts of the CSS should probably be parameterized so that you can pass values to it when you invoke the menu. Maybe.

  • You can pass as many items to this as you like (hence the use of the params string[] syntax in the helper method signature).

  • The original poster had noted that in some browsers, if the <ul> and <li> elements are on separate lines, the silly browser puts blank spaces between them. So a goal here was to smush everything together onto one line.

  • The menu text and menu target/link are separated by a pipe character ("|"). This was a quick-and-dirty thing. It might be more elegant to pass, say, 2-element arrays to the helper or something, but I generally think that invoking helpers in a page should be as straightforward as possible.

  • As coded, the links for the menu items have to be absolute. However, they really should be expressed, or at least expressable, using the ASP.NET ~ operator, which returns the virtual root, but which requires the ASP.NET Href method to resolve. I didn't bother.

  • For some reason I thought it was important to have logic in case a menu item was passed to the helper that didn't have a target in it. I can't offhand think of when this would ever be useful, tho.

I'm sure if I gave this another 5 minutes of thought I could improve it. And others could probably give it 10 seconds of thought, ditto. But it was fun while it lasted. :-)

[categories]   ,

[1] |