C# type casting

Hi,
I am new to C# and have not done much object oriented programming. Nevertheless, I have to create a 3 level dynamic and scalable menu in .NET 1.2, C# and ASP. C# is used to build and draw the menu.
Basically I have to create two classes "Menu" and "MenuItem".
"Menu" is a class that will have "Name", "URL",  "Children" variables. "MenuItem" class will have "Name" and "URL" variables. "Children"  is a collection of "MenuItem" objects and/or "Menu" objects. The idea is to use polymorphism so that if menu has a child that has a child we are using "Menu".
Each aspx page has several variables that are read by the menu script to know which section to highlight in the menu.

I am getting an error

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidCastException: Specified cast is not valid.

Source Error:


Line 90:                   
Line 91:                   foreach(object m in this.ChildMenu )
Line 92:                   {      Menu menu = (Menu)m; //cast it back to Menu object
Line 93:                         //error handeling
Line 94:                         if(menu._childMenu != null)
 

Source File: C:\Inetpub\wwwroot\DIR006\dev\root\ontario\business\test2.aspx    Line: 92


here is the code


<%@ Page Language="c#" %>
<%@ Import namespace="System"%>
<%@ Import namespace="System.Collections"%>
<script language="c#" runat="server">

 
public class Menu
{
      
      //region private fields      
      private string _menuName;      
      private string _linkUrl;
      private int _menuLevel;      
      private ArrayList _childMenu;
      
      //private string _childMenu;
      //endregion

      public Menu(){
            this._menuName = "";
            this._linkUrl = "";
            this._menuLevel = 0;
            this._childMenu = new ArrayList();
      }//end Nav
      
      public Menu(string mName, string mUrl, int mLevel)
      {
            this._menuName = mName;
            this._linkUrl = mUrl;
            this._menuLevel = 0;
            this._childMenu = new ArrayList();
            
      
      }//end Nav
      
      public Menu(string mName, string mUrl, ArrayList chMenu, int mLevel )
      {
            this._menuName = mName;
            this._linkUrl = mUrl;
            this._menuLevel = mLevel;
            this._childMenu = chMenu;
      }//end Nav

      public string MenuName
      {
            get { return _menuName; }
            set { _menuName = value; }
      }

      
      public string LinkUrl
      {
            get { return _linkUrl; }
            set { _linkUrl = value; }
      }
      
      public int MenuLevel
      {
            get { return _menuLevel; }
            set { _menuLevel = value; }
      }
      
      public ArrayList ChildMenu
      {
            get { return _childMenu; }
            set { _childMenu = value; }
      }
      
            
      public string printMenu()
      {      
            string menuNav = "";
            
            
            //build menu with no subsection
            if(this._childMenu == null)
            {
                  if(this._childMenu[0] is MenuItem)
                  {            
                        //loop through the menuItems. create menues without subsections            
                        foreach(MenuItem item in this.ChildMenu )
                        {      
                              menuNav += "<div id=\"menu_level" + item.MenuLevel + "\">" + item.printMenuItem().ToString() + "</div>";                                          
                        }
                        
                  }
            }
            else   /// menu with subsections
            {
                  
                  foreach(object m in this.ChildMenu )
                  {      Menu menu = (Menu)m; //cast it back to Menu object
                        //error handeling
                        if(menu._childMenu != null)
                        {                        
                              foreach(object sM in menu.ChildMenu )
                              {
                                    Menu subMenu = (Menu)sM; //cast it back to Menu object
                                    if(subMenu._childMenu != null)
                                    {                        
                                          foreach(object sCh in subMenu.ChildMenu)
                                          {
                                                Menu subChild = (Menu)sCh; //cast it back to Menu object
                                                menuNav += "<div id=\"menu_level" + subChild.MenuLevel + "\">" + subChild.printMenu().ToString() + "</div>";
                                          }                              
                                    }
                              }      
                        }
                        else
                        {
                              menuNav += "this menu should be using MenuItem object";
                        }
                  }
                        
            }
            
            return menuNav;      
            
      }
      
      //pint menues that have subsections
      public string drawNav()
      {                  
            return this.printMenu();            
                  
      }
      
      
      
      ///
      
      
      
}

///////////////////////////MenuItem//////////////////////////////////////////////////////
public class MenuItem
{
      private string _menuName;      
      private string _linkUrl;      
      private int _menuLevel;
      private ArrayList _childMenu;
      
      //endregion

      
      public MenuItem(){
            this._menuName = "";
            this._linkUrl = "";
            this._menuLevel = 0;
      }//end Nav
      
      public MenuItem(string mName, string mUrl, int mLevel){
            this._menuName = mName;
            this._linkUrl = mUrl;
            this._menuLevel = mLevel;
            
      }//end Nav
      
      //get and set
      public string MenuName
      {
            get { return _menuName; }
            set { _menuName = value; }
      }

      
      public string LinkUrl
      {
            get { return _linkUrl; }
            set { _linkUrl = value; }
      }
      
      public int MenuLevel
      {
            get { return _menuLevel; }
            set { _menuLevel = value; }
      }
      
      ///print items
      public string printMenuItem()
      {      
            string menuNav = "";            
            
            //menuNav += "<div id=\"menu_level2\">";
            menuNav += "<a href=\"" + this._linkUrl + "?WT.svl=nav\">" + this._menuName + "</a>";            
            //menuNav +=  + "</div>";
                        
            return menuNav;
      }      
      
      
}



</script>

<body>
<div id="main">
<%


MenuItem oMenuItem = new MenuItem();
Menu oMenu = new Menu();

//direct Energy Business srvices section
oMenuItem = new MenuItem("Business Services","/ontario/business/default.aspx",1);
oMenu.ChildMenu.Add(oMenuItem);


//Doing Business with Direct Energy section
oMenuItem = new MenuItem("Consultative Process","/ontario/business/business_with_direct/consultive_process.aspx",2);
oMenu = new Menu("Doing Business","/ontario/business/business_with_direct/default.aspx",1);
oMenu.ChildMenu.Add(oMenuItem);

            
Response.Write("<div style=\"width:146px;\">");
Response.Write("" + oMenu.drawNav());
Response.Write("</div>");

%>
</div>
</body>
ashevelAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
vo1dConnect With a Mentor Commented:
to my opinion, your design has a failure.
it is not a good way to store two different types in the same arraylist.

you should setup a different design:
every entry is of type menutitem which has a reference to its parent menuitem and an arraylist(better would be an own menuitem collection) with subitems.
these subitems are also menuitems.

so your object design should look like similar to this(its hacked in this experts-exchange textbox and is NOT tested -> its only to push you in the correct direction):
public class MenuItem
{
     //region private fields    
     private Menuitem _parentMenuItem;
     private string       _menuTitle;    
     private string       _linkUrl;
     private int            _menuLevel;    
     private ArrayList   _subMenuItems;

     public MenuItem(string MenuTitle, string mUrl, int mLevel, MenuItem parentMenuItem)
     {
          this._menuName         = MenuTitle;
          this._linkUrl                = mUrl;
          this._menuLevel          = mLevel;
          this._parentMenuItem = parentMenuItem
          this._subMenuItems    = new ArrayList();        
     }    
     //get and set
     public string MenuName
     {
          get { return _menuName; }
          set { _menuName = value; }
     }

     
     public string LinkUrl
     {
          get { return _linkUrl; }
          set { _linkUrl = value; }
     }
     
     public int MenuLevel
     {
          get { return _menuLevel; }
          set { _menuLevel = value; }
     }
     
     public MenuItem ParentMenuItem
     {
          get { return _parentMenuItem; }
          set { _parentMenuItem= value; }
     }

      public ArrayList SubMenuItems
     {
          get { return _subMenuItems; }
     }
     ///print items
     public string printMenuItem()
     {    
          string menuNav = "";          
         
          //menuNav += "<div id=\"menu_level2\">";
          menuNav += "<a href=\"" + this._linkUrl + "?WT.svl=nav\">" + this._menuName + "</a>";          
          //menuNav +=  + "</div>";
                   
          return menuNav;
     }  

     //add a submenuitem
    public MenuItem AddSubMenuItem(string MenuTitle, string mUrl)
    {
       MenuItem newItem = new MenuItem(MenuTitle, mUrl, this._menuLevel+1, this)
       this._subMenuItems.Add(newItem);
       return(newItem);
    }
   
    //get a submenuitem
    public MenuItem GetSubMenuItem(int index)
    {
       return(index < this._subMenuItems.Count ? this._subMenuItems[index] : null);
    }

    public MenuItem GetSubMenuItem(string SubMenuTitle)
    {
       foreach(MenuItem currentItem in this._subMenuItems)
       {
         if(currentItem._menuName == SubMenuTitle)
         {
           return (currentItem);
         }
       }
       return (null);
   }
}


now you can make something like this:

MenuItem mainMenuItem1 = new MenuItem("Menu1", "www.link.com", 0, null);
mainMenuItem1.AddSubMenuItem("ChildMenu1", "www.link.com"); //will automatically level1 and has parent mainMenuItem
MenuItem subMenuItemOfMainMenuItem1 = mainMenuItem1.AddSubMenuItem("ChildMenu2", "www.link.com") //will also have level1 and parent mainMenuItem
subMenuItemOfMainMenuItem1.AddSubMenuItem("Childmenu4", "www.link.com"); //will automatically level2 and has parent subMenuItemOfMainMenuItem1

that tree would look like this:

Menu1
    ChildMenu1
    ChildMenu2
        ChildMenu4


0
 
vo1dCommented:
this.ChildMenu is of type arraylist, not of type Menu.

you declared it here:

private ArrayList _childMenu;

public ArrayList ChildMenu
     {
          get { return _childMenu; }
          set { _childMenu = value; }
     }

you will have to cast it to arraylist:
foreach(object m in this.ChildMenu )
{     ArrayList menu = (ArrayList )m;
      //error handeling
      if(menu._childMenu != null)
     

to loop through all your chidmenues, i would recommend a recursive method for that.
0
 
ashevelAuthor Commented:
foreach(object m in this.ChildMenu )
{     ArrayList menu = (ArrayList )m;
      //error handeling
      if(menu._childMenu != null)
 

 I get an error :

Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: CS0117: 'System.Collections.ArrayList' does not contain a definition for 'MenuLevel'

Source Error:

 

Line 104:                        
Line 105:                        
Line 106:                        menuNav += "<div id=\"menu_level" + menu.MenuLevel + "\">" + menu.printMenu().ToString() + "</div>";
Line 107:                        if(menu._childMenu != null)
Line 108:            
 
     
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
ashevelAuthor Commented:
ArrayLists contains objects that have parameters that I need to access. so I need to declare object handl some how to get access to parameters in array list
0
 
vo1dCommented:
no it cant have such a property, because the field menu is of type arraylist and not of type Menu.
why do you use an arraylist?
it only makes sense, if you add more than one Menu instance to it.
0
 
ashevelAuthor Commented:
that's the idea. I am adding more instanses of Manu and MenuItem to the array list.
0
 
ashevelAuthor Commented:
I am using polymorphism and recurcive method... this is sort of the idea.
//first level
Menu
  Name: "Menu1"
  Url: "www.link.com"
  Children:
              //second level
               MenuItem:
                    Name: "ChildMenu1"
                    URL: "www.link.com"

               Menu:
                    Name: "ChildMenu2'
                    URL: "....."
                    Children:
                    //third level
                                MenuItem:
                                    Name: "Childmenu4"
                                    Url: "...."
//first level
MenuItem
  Name: "Menu1"
  Url: "www.link.com"
  Children:

//first level
Menu
  Name: "Menu1"
  Url: "www.link.com"
  Children:
              //second level
               MenuItem:
                    Name: "ChildMenu1"
                    URL: "www.link.com"
             
0
 
BowmanjeCommented:
ashevel,

In order to use polymorphism, both classes need to derive from a base class.  In this case, it would seem appropriate to derive Menu from MenuItem since it is both an item in its parent's menu as well as a menu itself.  Since neither class appears to extend a common base class and you add all your items to the arraylist as MenuItem, the cast to Menu is invalid. Try this...

class Menu : MenuItem
{
   ...
}

Additionally, you do not need to declare MenuName, LinkUrl, ChildMenu, or MenuLevel properties in Menu, since they are already declared in MenuItem.

HTH,
Josh
0
 
BowmanjeCommented:
Oh, in my previous post, either your private fields would need to be declared protected, or you would need to redo you constructors. Such as...

public Menu(string mName, string mUrl, ArrayList chMenu, int mLevel ) : base(mName, mUrl, chMenu, mLevel)
     {
         
     }//end Nav

-Josh
0
 
ashevelAuthor Commented:
"you add all your items to the arraylist as MenuItem, the cast to Menu is invalid. "
Bowmanje,
I will aslo have to add items to the arraylist as Menu if the menu has children. Menu is the the class that has arrayList. the code I provided was somewhat incomplete...
for example:

MenuItem oMenuItem = new MenuItem();
Menu oMenu = new Menu();

// section1
oMenu = new Menu("Business Services","/ontario/business/default.aspx",1);
oMenu.ChildMenu.Add(oMenu);

//section2
oMenu = new Menu("Doing Business","/ontario/business/business/default.aspx",1);
oMenuItem = new MenuItem("Consultative Process","/ontario/business/business_with_direct/consultive_process.aspx",2);

oMenu.ChildMenu.Add(oMenuItem);
oMenu.ChildMenu.Add(oMenu);

//section3
MenuItem oSubMenu = MenuItme;
oMenu = new Menu("blah","/ontario/business/business/default.aspx",1);
oSubMenu = new Menu("blablah","/ontario/business/business_direct/process.aspx",2);
oMenuItem = new MenuItem("Menu Level3","/ontario/business/business_with_direct/consultive_process.aspx",3);

oSubMenu.ChildMenu.Add(oMenuItem);
oMenu.ChildMenu.Add(oSubMenu);
oMenu.ChildMenu.Add(oMenu);
0
All Courses

From novice to tech pro — start learning today.