Saturday, February 19, 2011

How to make 4 columns across in ASP.NET MVC - How to make my current code suck less

I have the following code, I'm trying to get a table with 4 columns across. If I run out of columns, create a new row and make 4 more coumns. rinse. lather. repeat.

<tbody>
<%
int i = 0;
foreach (ItmXtnMultimedia multimedia in ViewData.Model.ItmXtnMultimedia) {
  if (i%4 == 0 && i== 0)
  {
    %><tr><%
  }
  if (i%4 == 0 && i != 0)
  {
    %></tr><tr><%
  }
  %>                    
  <td><%= multimedia.ImgTag100 %></td>                            
  <%
  i++;
  } %>

It works, but it sucks. Is there something built in to the framework or an extension method I can use? I guess I could roll my own, but figured there had to be something out there.

From stackoverflow
  • I'd recommend looking at Tablebuilder. It is written in C# 3.0, and does what you need it to do, from what I can gather.

  • You should replace the second if with else if.. Other than that, it's okay.

    foreach (ItmXtnMultimedia multimedia in ViewData.Model.ItmXtnMultimedia) 
    {
      if (i%4 == 0 && i== 0)
      {
          %><tr><%
      }
      else if (i%4 == 0 && i != 0)
      {
          %></tr><tr><%
      }
      %><td><%= multimedia.ImgTag100 %></td><%
      i++;
    }%>
    
  • Actually, I popped the fir out of the loop... (still smells though)

                    <tbody>
                        <tr>
                        <%
                        int i = 0;
                        foreach (ItmXtnMultimedia multimedia in ViewData.Model.ItmXtnMultimedia) {
    
                            if (i%4 == 0)
                            {
                                %></tr><tr><%
                            }
                            %>                    
                            <td><%= multimedia.ImgTag100 %></td>                            
                            <%
                            i++;
                        } %>                    
                    </tbody>
    
    Kyle West : parser killed half my first comment. I took the first tr tag out of the the loop.
  • What about a little refactor?

    <%
    foreach (ItmXtnMultimedia multimedia in ViewData.Model.ItmXtnMultimedia) {
      manageColumnsForMe( 4 )
      %><td><%= multimedia.ImgTag100 %></td><%
      } 
    %>
    

    And the put the other code in a function using a static variable to store i

    You can reuse the same function with different number of columns

  • I am assuming ViewData.Model.ItmXtnMultimedia is a list of some sort:

    <tbody>
    <%
        for (int i = 0; i < ViewData.Model.ItmXtnMultimedia.Count; i++ )
        {
            %><tr><%
            for (int j = 0; i < 4; j++)
            {
                if (i < ViewData.Model.ItmXtnMultimedia.Count)
                {
                    %><td><%= ViewData.Model.ItmXtnMultimedia[i].ImgTag100 %> %></td><%
                }
                else
                {
                    %><td></td><%
                }
            }
            %></tr><%
        } 
    %>
    </tbody>
    

    Still a mess of code, but maybe more readable?

  • This is a good place to create an extension method. Here's some almost-compilable C# pseudocode:

    public static void IDunnoWhatToCallThis<T>(
        this HtmlHelper me, 
        T[] items,
        int columns,
        Action headerTemplate,
        Action<T> itemTemplate,
        Action newRowTemplate,
        Action footerTemplate )
    {
      headerTemplate();
    
      for(int i = 0;i < items.Length; i++)
      {
        if(i != 0 && i%columns == 0)
          newRowTemplate();
    
        itemTemplate(items[i]);
      }
    
      footerTemplate();
    }
    

    And here's an example in use:

    <% Html.IDunnoWhatToCallThis(
      ViewData.Model.ItmXtnMultimedia,
      4,
      () => %><table><tr><%,
      (item) => %><td><%= item.ImgTag100 %></td><%,
      () => %></tr><tr><%,
      () => %></tr></table><%);%>
    

    I LOVE helpers like this, mixing inline code, lambdas and markup. Its like watching magic.

0 comments:

Post a Comment