ViewData and Foreach

Last post 05-11-2009 4:46 PM by loveriysa. 5 replies.

Sort Posts:

  • ViewData and Foreach

    05-06-2009, 4:07 AM
    • Member
      1 point Member
    • loveriysa
    • Member since 05-04-2009, 8:46 PM
    • Posts 5

    Hey guys, I am trying to pass data in my Master page by implementing classes as below:

     

    File: ~/Controllers/ATController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Mvc.Ajax;
    using Gateway.Library;

    namespace Gateway.Controllers
    {
    public abstract class ATController : Controller
    {
    protected override void Initialize(System.Web.Routing.RequestContext requestContext) {
    base.Initialize(requestContext);

    ATMenu menu = new ATMenu();
    menu.Add("Home", "Home", "Index");
    menu.Add("The Market", "Market", "Index");
    menu.Add("News & Talk", "News", "Index");
    menu.Add("The Committee", "Committee", "Index");
    menu.Add("Research & Tools", "Research", "Index");
    menu.Add("My Portfolio", "Users", "Portfolio", new List<ATPage>() {
    new ATPage("Users", "Register"),
    new ATPage("Users", "Login")
    });

    ViewData["menu"] = menu;
    }
    }
    }
     
    File: ~/Library/ATMenu.cs
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    namespace Gateway.Library {
        public class ATMenu {
            private List<ATMenuItem> _items = new List();
            public List items {
                get { return _items; }
            }
            public void Add(string title, string controller, string action) {
                this._items.Add(new ATMenuItem(title, controller, action));
            }
            public void Add(string title, string controller, string action, List pages) {
                this._items.Add(new ATMenuItem(title, controller, action, pages));
            }
        }
    }
    
     
    File: ~/Library/ATMenuItem.cs
    
    using System;
    using System.Collections.Generic;
    namespace Gateway.Library {
        public class ATMenuItem {
            private string _title;
            public string title {
                get { return _title; }
            }
            private string _controller;
            public string controller {
                get { return _controller; }
            }
            private string _action;
            public string action {
                get { return _action; }
            }
            private List<ATPage> ActiveIn = new List();
            public ATMenuItem(string title, string controller, string action) {
                this.__MenuItem(title, controller, action);
                this.Activate(new ATPage(this.controller, this.action));
            }
            public ATMenuItem(string title, string controller, string action, List pages) {
                this.__MenuItem(title, controller, action);
                this.Activate(new ATPage(this.controller, this.action));
                if (pages.Count > 0) {
                    foreach (ATPage p in pages) {
                        this.Activate(p);
                    }
                }
            }
            private void __MenuItem(string title, string controller, string action) {
                this._title = title;
                this._controller = controller;
                this._action = action;
            }
            public void Activate(ATPage p) {
                if (!this.IsActiveIn(p)) {
                    this.ActiveIn.Add(p);
                }
            }
            public bool IsActiveIn(ATPage p) {
                return this.ActiveIn.Contains(p);
            }
        }
    }
     
    File: ~/Library/ATPage.cs
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    namespace Gateway.Library {
        public class ATPage {
            private string _controller;
            public string controller { get { return _controller; } }
            private string _action;
            public string action { get { return _action; } }
            public ATPage(string controller, string action) {
                this._controller = controller;
                this._action = action;
            }
        }
    }
     
    File: ~/Views/Shared/Site.Master
    
    <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
    <%@ Import Namespace="Gateway.Library" %>
    <ul>
      <%foreach (ATMenu menu in (IEnumerable)ViewData["menu"]) { %>
        <%foreach (ATMenuItem m in menu.items) { %>
          
    
  • <%=m.title %>
  • <%} %> <%} %>

     It compiles fine, but whenever I run the application I get the following error:

     

    Unable to cast object of type 'Gateway.Library.ATMenu' to type 'System.Collections.Generic.IEnumerable`1[Gateway.Library.ATMenu]'.

      

    I am sure I must be ignoring something really simple and basic. But not able to figure out as of now.

    Would you be please so kind to help me out here?

     

    Thank you

    Filed under: , ,
  • Re: ViewData and Foreach

    05-06-2009, 5:17 AM
    Answer
    • Member
      158 point Member
    • Ivan Makarevich
    • Member since 02-06-2009, 1:39 PM
    • Europe, Belarus, Minsk
    • Posts 38

    Symple answer:

    Unable to cast object of type 'Gateway.Library.ATMenu' to type 'System.Collections.Generic.IEnumerable`1[Gateway.Library.ATMenu]'.

    Is becouse the Gateway.Library.ATMenu is not IEnumerable. Really.

    Only Gateway.Library.ATMenu.items property is IEnumerable. Right code:

    <ul>
    <%foreach (ATMenu menu in (IEnumerable)((ATMenu)ViewData["menu"]).items)) { %>
    <%foreach (ATMenuItem m in menu.items) { %>

  • <%=m.title %>

  • <%} %>
    <%} %>
    Don't forget to click "Mark as Answer" on the post that helped you.
  • Re: ViewData and Foreach

    05-06-2009, 11:11 AM
    • Member
      1 point Member
    • loveriysa
    • Member since 05-04-2009, 8:46 PM
    • Posts 5

    Thanks a lot. It sure did the trick :)

    Here is the final code I am using hope it proves helpful to some other newbie like me :)

     

    <ul>
    <%foreach (ATMenuItem m in (IEnumerable)((ATMenu)ViewData["menu"]).items) { %>
  • <%=m.title %>

  • <%} %>

      

    Btw, could anyone please help me understand this concept of "Enumerable" I am having some hard time understanding well from many resources available online. Is there any explanation in very simple and easy to understand terms?

     

    Thank you

  • Re: ViewData and Foreach

    05-07-2009, 3:42 AM
    • Member
      158 point Member
    • Ivan Makarevich
    • Member since 02-06-2009, 1:39 PM
    • Europe, Belarus, Minsk
    • Posts 38

     First: There are a lot of clases which implements IEnumerable<T> in NET Framework. Usually you don't need to implement it by yourself.

    Second: There is a "C# 3.0 language specification " somewhere in msdn. It is very userfull doc.

    Third: If you want to add some abilities to List<ATMenuItem> better derive from it: 

    1        public class AtMenu : List<AtMenuItem> {
    2 public void Add(string title, string controller, string action) {
    3 Add(new AtMenuItem(title, controller, action));
    4 }
    5 public void Add(string title, string controller, string action, List pages) {
    6 Add(new AtMenuItem(title, controller, action, pages));
    7 }
    8 }
      Forth: There is the "Auto property" feature in C# 3.0. It makes code more clean and increase readability.
     
    1        public class AtMenuItem
    2 {
    3 public string Title { get; private set; }
    4 public string Controller { get; private set; }
    5 public string Action { get; private set; }
    6 }
     
    Fifth: There is ability to call another constructor from current:
      
    1        public class AtMenuItem {
    2 #region Constructors
    3
    4 public AtMenuItem(string title, string controller, string action) {
    5 Title = title;
    6 Controller = controller;
    7 Action = action;
    8 this.Activate(new AtPage(this.controller, this.action));
    9 }
    10
    11 public AtMenuItem(string title, string controller, string action, List pages) : this(title, controller, action) {
    12 if (pages.Count > 0) { // it is redundant. Better check for null.
    13 foreach (AtPage p in pages) {
    14 this.Activate(p);
    15 }
    16 }
    17 }
    18
    19 #endregion
    20
    21 #region
    Properties
    22
    23 public string Title { get; private set; }
    24 public string Controller { get; private set; }
    25 public string Action { get; private set; }
    26
    27 #endregion
    28
    29 #region
    Methods
    30
    31 // other methods
    32
    33 #endregion
    34 }
     And exists naming convention for C#. :)
     
    Don't forget to click "Mark as Answer" on the post that helped you.
  • Re: ViewData and Foreach

    05-07-2009, 8:22 AM
    • Participant
      1,257 point Participant
    • littlefool
    • Member since 03-05-2004, 6:28 AM
    • Brussels, Belgium
    • Posts 248

    loveriysa:
    Btw, could anyone please help me understand this concept of "Enumerable" I am having some hard time understanding well from many resources available online. Is there any explanation in very simple and easy to understand terms?

    "Enumerable" classes collections provide an easy way to itterate through their child objects. In short, it allows you to use the foreach statement on your collection of objects.
    Most of the .NET collections already provide this feature, but if you really want to create a new collection from scratch, and want to have to foreach going over it, you will need to implement the IEnumerable interface on that class.
    See article below for a little more detailed information:

    http://www.codeproject.com/KB/cs/csenumerators.aspx

    "Dream as if you'll live forever, live as if you'll die today" (James Dean)
  • Re: ViewData and Foreach

    05-11-2009, 4:46 PM
    • Member
      1 point Member
    • loveriysa
    • Member since 05-04-2009, 8:46 PM
    • Posts 5

     It is very helpful! Thanks a lot :)

Page 1 of 1 (6 items)