An Agreeable Procrastination – and the blog of Niels Kühnel

Code, the universe and everything

Recursive functions in markup (fun with delegates)

leave a comment »

Sometimes it would be nice to do recursive functions in user controls (for instance, when doing menus).
You can’t define functions like void RenderMenu(IEnumerable<MenuItem> items, int level) { ... } in markup files unless you’re up for some serious Response.Write’ing in a <script runat=”server”> block (which kind of kills the purpose of markup files in the first place). What you can do, however, is to assign values to variables and these values can be delegates.

So you can go like this:

Action<IEnumerable<MenuItem>, int> renderMenu = null;
renderMenu = (items, level) => {
    %><ul class="level-<%=level>"><%
    foreach( var item in items ) {
      <li><a href="<%=item.Url>"><%=item.Title%></a>
      <%if( item.Children.Any() ) {
           renderMenu(item.Children, level + 1);

renderMenu(MyMenuItems, 1);

It’s surprising that you can embed HTML in a delegate, but if you know how the ascx parser works it’s probably obvious (I don’t).

Now, it’s important to assign “null” to the delegate variable first, and then assign the actual function in a later statement. Otherwise you can’t do recursion because the compiler complaints about the variable not beeing initialized.

The fact that you have to do “Action<bla, bla, bla...> foo = null; foo = (bla, bla, bla..) { ... }” to define the function is arguably not very aesthetically pleasing. It’s also a shame that you must define the function before you use it. But if you use this construction a lot you’ll probably just get used to it as the way it is, and it’s really convenient to be able to do recursion in markup – with embedded markup.

(How about casing? It’s a local variable so it should be camelCased. But it’s used as a way – don’t say hack 😛 – to have a method. So should it be PascalCased?)


Written by niels.kuhnel

August 11, 2010 at 10:37 pm

Posted in ASP.NET

Tagged with ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: