Solved

C# type casting

Posted on 2006-06-22
13
352 Views
Last Modified: 2012-08-13
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>
0
Comment
Question by:ashevel
  • 5
  • 3
  • 2
13 Comments
 
LVL 11

Expert Comment

by:vo1d
ID: 16964247
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
 

Author Comment

by:ashevel
ID: 16964577
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
 

Author Comment

by:ashevel
ID: 16964599
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
 
LVL 11

Expert Comment

by:vo1d
ID: 16964608
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
 

Author Comment

by:ashevel
ID: 16964633
that's the idea. I am adding more instanses of Manu and MenuItem to the array list.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:ashevel
ID: 16964690
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
 
LVL 3

Expert Comment

by:Bowmanje
ID: 16968986
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
 
LVL 3

Expert Comment

by:Bowmanje
ID: 16969131
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
 

Author Comment

by:ashevel
ID: 16969591
"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
 
LVL 11

Accepted Solution

by:
vo1d earned 500 total points
ID: 16970943
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now