Building multiple column displays in MVC

By James at January 12, 2011 16:34
Filed Under: ASP.NET

Looping through a list of objects to display a table of the items is easy in MVC. All you need to do is:

   1: <table>
   2: <%foreach (var item in friendList){%>
   3:   <tr>
   4:     <td><%item.Friend.FullName %></td>
   5:   </tr>
   6: <%}%>
   7: </table>

But what if your display calls for a multi-column layout, say with 4 columns and an unknown number of rows? I have pondered this over and over in many of my projects and have come up with the following code to do this. I have a helper file which my Controller calls to build a string of div tags to display the results. It may look complicated but I will go over the details below.

   1: public string GetAvailableFriends(int memberId)
   2: {
   3:   var list = _repo.List<Member>().Where(m => m.MemberContact.Equals(true))
   4:              .OrderBy(m => m.FirstName).ToList();
   5:   var memberFriends = _repo.List<MemberFriend>()
   6:             .Where(m => m.Member.Id.Equals(memberId)).ToList();
   7:             
   8:   var currentFriends = memberFriends.Select(f => f.Friend).ToList();
   9:  
  10:   var availableFriendList = (from friend in list
  11:                              where !currentFriends.Contains(friend)
  12:                              select new MemberFriends
  13:                             {
  14:                              FirstName = friend.FirstName, 
  15:                              LastName = friend.LastName,
  16:                              FriendId = friend.Id, 
  17:                              FullName = friend.FirstName + " " + friend.LastName,
  18:                              Avatar = friend.Avatar
  19:                              }).ToList();
  20:  
  21:   decimal listCount = availableFriendList.Count;
  22:   var listLimit = Math.Floor(listCount / 4) + 2;
  23:   if (listLimit == 0) listLimit = 1;
  24:   var addedFriends = 0;
  25:             
  26:   var friendTable = new StringBuilder("<div class='availFriends'>");
  27:             
  28:   for (var i = 0; i < listLimit; i++)
  29:   {
  30:      if (addedFriends >= listCount) continue; // we're all done, no need to continue
  31:  
  32:      friendTable.Append(i < listLimit - 1 ? "<div class='row availFriendRow'>" : "<div class='row last'>");
  33:  
  34:      //first column
  35:      if (addedFriends < listCount)
  36:      {
  37:        var friend1 = availableFriendList.ElementAt(addedFriends);
  38:        var avatarSource = _photoHelpers.GetAvatarThumbSource(friend1);
  39:        FriendTableAppend(friendTable, friend1, avatarSource);
  40:        addedFriends++;
  41:      }
  42:  
  43:      //second column
  44:      if (addedFriends < listCount)
  45:      {
  46:        var friend2 = availableFriendList.ElementAt(addedFriends);
  47:        var avatarSource = _photoHelpers.GetAvatarThumbSource(friend2);
  48:        FriendTableAppend(friendTable, friend2, avatarSource);
  49:        addedFriends++;
  50:      }
  51:      
  52:      //third column
  53:      if (addedFriends < listCount)
  54:      {
  55:        var friend3 = availableFriendList.ElementAt(addedFriends);
  56:        var avatarSource = _photoHelpers.GetAvatarThumbSource(friend3);
  57:        FriendTableAppend(friendTable, friend3, avatarSource);
  58:        addedFriends++;
  59:      }
  60:      
  61:      //fourth column
  62:      if (addedFriends < listCount)
  63:      {
  64:        var friend4 = availableFriendList.ElementAt(addedFriends);
  65:        var avatarSource = _photoHelpers.GetAvatarThumbSource(friend4);
  66:        FriendTableAppend(friendTable, friend4, avatarSource);
  67:        addedFriends++;
  68:      }
  69:  
  70:      friendTable.Append("</div>");
  71:   }
  72:   friendTable.Append("<div class='sendFriendRequest sendFriendRequestDisabled'>Send Friend Request</div>");
  73:   friendTable.Append("</div>");
  74:   return friendTable.ToString();
  75: }
  76:  
  77: private void FriendTableAppend(StringBuilder friendTable, MemberFriends friend, string avatarSource)
  78: {
  79:    friendTable.Append("<div class='col col225'>");
  80:    friendTable.Append("<div class='availFriendHolder'>");
  81:    friendTable.Append("<div class='availFriendCheckBox chkGraphic chkUnChecked' fxn='");
  82:    friendTable.Append(friend.FriendId + "'><input type='hidden' name='");
  83:    friendTable.Append(friend.FriendId + "'/></div>");
  84:    friendTable.Append("<div class='availFriendAvatar'><img src='" + avatarSource + "' /></div>");
  85:    friendTable.Append("<div class='availFriendName'>" + friend.FullName + "</div>");
  86:    if(FriendRequestPending(friend.FriendId))
  87:    {
  88:        friendTable.Append("<div class='friendRequestPending'>Friend Request Pending</div>");
  89:    }
  90:    friendTable.Append("</div>");
  91:    friendTable.Append("</div>");
  92: }
  93:  
  94: public bool FriendRequestPending(int friendId)
  95: {
  96:     var approved = false;
  97:     var memberFriend = _repo.List<MemberFriend>()
  98:         .Where(m => m.FriendId.Equals(friendId))
  99:         .ToList().FirstOrDefault();
 100:     if (memberFriend != null)
 101:         approved = memberFriend.Approved;
 102:     return approved;
 103: }

 

  1. The first thing to do is set the variable listCount to how many elements are in the list – line 21
  2. Set a variable, “listLimit” to listCount divided by the number of columns you want, in this case 4 – line 22
  3. If the result comes back as 0 then set it to 1 – line 23
  4. Set a variable “addedFriends” to 0 – line 24
  5. Start a loop – line 28
  6. Inside the loop, grab the element in the list that is indexed at “addedFriends” – lines 37, 46, 55, 64
  7. Call the helper method FriendTableAppend to continue building out the string.
  8. At the end of the loop, finish up the string, then return it.

 

Easy, peasy, nice and cheesy.

Happy Programming from ComponentOne

James

Comments (1) -

2/10/2012 5:31:15 PM #

Hristo

Execellent. Thanks

Hristo Bulgaria | Reply

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


About the author

James James is a five time and current Microsoft MVP in Client App Development, a Telerik Insider, a past Director on the INETA North America Board, a husband and dad, and has been developing software since the early days of Laser Discs and HyperCard stacks. As the Founder and President of the Inland Empire .NET User's Group, he has fondly watched it grow from a twice-a-month, early Saturday morning group of five in 2003, to a robust and rambunctious gathering of all types and sizes of .NET developers.

James loves to dig deep into the latest cutting edge technologies - sometimes with spectacular disasters - and spread the word about the latest and greatest bits, getting people excited about developing web sites and applications on the .NET platform, and using the best tools for the job. He tries to blog as often as he can, but usually gets distracted by EF, LINQ, MVC, ASP, SQL, XML, and most other types of acronyms. To keep calm James plays a mean Djembe and tries to practice his violin. You can follow him on twitter at @latringo.

And as usual, the comments, suggestions, writings and rants are my own, and really shouldn't reflect the opinions of my employer. That is, unless it really does.

James Twitter Feed

Recent Comments

Comment RSS

Month List