2012-09-10 54 views
0

我試圖從SQL Server 2008數據庫中獲取菜單項。從asp.net中的數據庫獲取菜單項

我用盡這樣的事情,因爲我用Google搜索了一圈,發現這些教程 firstsecond

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Data; 
using System.Data.SqlClient; 
using System.Configuration; 
using System.Text; 

namespace MenuDriven 
{ 
    public partial class MenuDB : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      menuBar.MaximumDynamicDisplayLevels = 3; 

      if (!IsPostBack) 
      { 

       SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString); 

       con.Open(); 
       DataSet ds = new DataSet(); 
       DataTable dt = new DataTable(); 
       string sql = "Select * from MenuItems"; 
       SqlDataAdapter da = new SqlDataAdapter(sql, con); 
       da.Fill(ds); 
       dt = ds.Tables[0]; 
       DataRow[] drowpar = dt.Select("ParentID=" + 0); 

       foreach (DataRow dr in drowpar) 
       { 
        menuBar.Items.Add(new MenuItem(dr["MenuName"].ToString(), 
          dr["MenuID"].ToString(), "", 
          dr["MenuLocation"].ToString())); 
       } 

       foreach (DataRow dr in dt.Select("ParentID >" + 0)) 
       { 
        MenuItem mnu = new MenuItem(dr["MenuName"].ToString(), dr["MenuID"].ToString(), 
        "", dr["MenuLocation"].ToString()); 

        //Code for Multiple Menu Levels 
        string valuePath = getValuePath(Convert.ToInt32(dr["ParentID"].ToString()), dt); 
        //menuBar.FindItem(dr["ParentID"].ToString()).ChildItems.Add(mnu); 
        menuBar.FindItem(valuePath).ChildItems.Add(mnu);**NullReferenceException was handled by the code** 
        //End Code for Multiple Menu Levels 
       } 
       con.Close(); 
      } 

     } 
     private string getValuePath(Int32 Parent, DataTable dt) 
     { 
      int predecessor = Parent; 
      StringBuilder valuePath = new StringBuilder(); 
      valuePath.Append(Parent.ToString()); 
      DataRow[] drPar; 
      while (true) 
      { 
       drPar = dt.Select("MenuID=" + predecessor); 
       if (drPar[0]["ParentID"].ToString().Equals("0"))**//Index out of range exception** 
        break; 
       valuePath.Insert(0, '/'); 
       valuePath.Insert(0, drPar[0]["ParentID"].ToString()); 
       predecessor = Convert.ToInt32(drPar[0]["ParentID"].ToString()); 
      } 
      return valuePath.ToString(); 
     } 

    } 
} 

我有兩個錯誤的驗證碼

  1. 索引超出範圍例外
  2. NullReferenceException由代碼處理

我已經指出了產生錯誤的代碼。

這是我的數據庫以及標題。

MenuID MenuName MenuLocation ParentID Value 
1  Parent1  NULL   0    p1 
2  Parent2  NULL   0    p2 
3  Parent3  NULL   0    p3 
11  SubMenuItem1  NULL   1    s1 
12  SubMenuItem2  NULL   1    s1 
21  SubMenuItem3  NULL   2    s1 
111  SubSubMenuItem4 NULL   1    ss1 
211  SubSubMenuItem5 NULL   2    ss1 

回答

3

我已經有了解決方案,用於菜單項任意數量的水平。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Data; 
using System.Data.SqlClient; 
using System.Configuration; 

namespace MenuDriven 
{ 
    public partial class AnotherMenuTest : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      populateMenuItem(); 
     } 
     private void populateMenuItem() 
     { 

      DataTable menuData = GetMenuData(); 
      AddTopMenuItems(menuData); 

     } 

     private DataTable GetMenuData() 
     { 
      using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServerString"].ConnectionString)) 
      { 
       using (SqlCommand cmd = new SqlCommand("SELECT MenuID,MenuName,ParentID FROM MenuItems", con)) 
       { 
        SqlDataAdapter da = new SqlDataAdapter(cmd); 
        DataTable dt = new DataTable(); 
        da.Fill(dt); 
        return dt; 
       } 

      } 
     } 

     /// Filter the data to get only the rows that have a 
     /// null ParentID (This will come on the top-level menu items) 

     private void AddTopMenuItems(DataTable menuData) 
     { 
      DataView view = new DataView(menuData); 
      view.RowFilter = "ParentID = 0"; 
      foreach (DataRowView row in view) 
      { 
       MenuItem newMenuItem = new MenuItem(row["MenuName"].ToString(), row["MenuID"].ToString()); 
       menuBar.Items.Add(newMenuItem); 
       AddChildMenuItems(menuData, newMenuItem); 
      } 

     } 

     //This code is used to recursively add child menu items by filtering by ParentID 

     private void AddChildMenuItems(DataTable menuData, MenuItem parentMenuItem) 
     { 
      DataView view = new DataView(menuData); 
      view.RowFilter = "ParentID=" + parentMenuItem.Value; 
      foreach (DataRowView row in view) 
      { 
       MenuItem newMenuItem = new MenuItem(row["MenuName"].ToString(), row["MenuID"].ToString()); 
       parentMenuItem.ChildItems.Add(newMenuItem); 
       AddChildMenuItems(menuData, newMenuItem); 
      } 
     } 
    } 
} 

感謝KnowledgeSeeker和Antonio的回覆。

和數據庫是這樣的。

這是我的數據庫以及標題。

MenuID MenuName MenuLocation ParentID  
1   Parent1    NULL   0    
2   Parent2    NULL   0    
3   Parent3    NULL   0    
11   SubMenuItem1 NULL   1    
12   SubMenuItem2 NULL   1    
21   SubMenuItem3 NULL   2    
111  SubSubMenuItem4  NULL   1    
211  SubSubMenuItem5  NULL   2   

解決辦法是: 設置數據庫本身內的父節點。

例:插入dbo.MenuItems值(333, 'SubSubMenuItem8',NULL,21)

這將設置SubSubMenuItem8爲孩子父節點SubMenuItem3

0

你必須通過PARENTID數據環槽表進行排序,然後和每個項目找到父項目,並將其添加到它的ChildItems,如果你沒有找到父項目添加到根。

獲取數據:

string sql = "Select * from MenuItems Order By ParentID"; 
DataTable data = GetTable(sql); 

然後填寫菜單:

foreach (DataRow rw in data.Rows) 
    { 
    IEnumerable<MenuItem> menuItems = Extensions.GetItems<MenuItem>(menuBar.Items, item => item.ChildItems); 

    MenuItem parent = menuItems.FirstOrDefault(mi => mi.Value == rw.Field<int>("ParentID").ToString()); 
    MenuItem newItem = new MenuItem(rw.Field<string>("MenuName"), rw.Field<int>("MenuID").ToString()); 
    if (parent == null) 
     menuBar.Items.Add(newItem); 
    else 
     parent.ChildItems.Add(newItem); 
    } 

這裏是GetItems方法將返回所有樹節點,從這裏取:https://stackoverflow.com/a/1815600/351383

public static class Extensions 
    { 
    public static IEnumerable<T> GetItems<T>(this IEnumerable collection, Func<T, IEnumerable> selector) 
    { 
     Stack<IEnumerable<T>> stack = new Stack<IEnumerable<T>>(); 
     stack.Push(collection.OfType<T>()); 

     while (stack.Count > 0) 
     { 
     IEnumerable<T> items = stack.Pop(); 
     foreach (var item in items) 
     { 
      yield return item; 

      IEnumerable<T> children = selector(item).OfType<T>(); 
      stack.Push(children); 
     } 
     } 
    } 
    } 
+0

安東尼奧,我可以看到第二個輸出但我無法看到第三級菜單項。這是投擲錯誤,指出'空引用異常' –

+0

您的getValuePath返回null,請嘗試調試以查看原因。但嘗試這個解決方案,它更簡單,將無限數量的水平 –

+0

我不發現它是什麼給錯誤。在你的代碼 –

1

按照以下示例修改您的代碼。我正在使用following菜單。據工作可能需要修改代碼根據自己的需要

  String sqlQuery = "SELECT * FROM pMenuItems"; 

      dsMenu = DataProvider.Connect_Select(sqlQuery); 

      DataTable tableMenu = dsMenu.Tables[0]; 
      DataView dvMenu = new DataView(tableMenu); 
      //dvMenu.RowFilter = "PageInheritance is NULL"; 
      dvMenu.RowFilter = "PageInheritance = 0"; 
      int dsMenuRowCount = dsMenu.Tables[0].Rows.Count; 
      //Create Top Menu 
      //StringBuilder sb = new StringBuilder(); 
      StringBuilder sbMenuFooter = new StringBuilder(); 
      if (dsMenu != null && dsMenu.Tables.Count > 0 && dsMenu.Tables[0].Rows.Count > 0) 
      { 
       foreach (DataRowView row in dvMenu) 
       { 
        // MenuItem menuItem = new MenuItem(row["MenuName"].ToString().ToUpper(), row["MenuID"].ToString()); 
        MenuItem menuItem = new MenuItem(row["PageName"].ToString(), row["PageId"].ToString()); 
        bool PageInternalLink = bool.Parse(row["PageInternalLink"].ToString()); 
        if (PageInternalLink == true) 
        { 
         menuItem.NavigateUrl = row["PageURL"].ToString() + "?PageId=" + row["PageId"]; 
        } 
        else 
        { 
         menuItem.NavigateUrl = row["PageURL"].ToString(); 
         menuItem.Target = row["PageWindow"].ToString(); 
        } 
        //menuItem.Target = 
        Menu1.Items.Add(menuItem); 
        AddChildItems(tableMenu, menuItem, PageInternalLink); 
       } 

private static void AddChildItems(DataTable table, MenuItem menuItem, bool PageInternalLink) 
{ 
    DataView viewItem = new DataView(table); 
    viewItem.RowFilter = "PageInheritance = " + menuItem.Value; 
    //foreach (DataRowView row in dvMenu) 
    foreach (DataRowView childView in viewItem) 
    { 
     MenuItem childItem = new MenuItem(childView["MenuName"].ToString(), childView["MenuID"].ToString()); 
     childItem.NavigateUrl = childView["PageURL"].ToString() + "?PageId=" + childView["PageId"]; 
     if (PageInternalLink == true) 
     { 
      childItem.NavigateUrl = childView["PageURL"].ToString() + "?PageId=" + childView["PageId"]; 
     } 
     else 
     { 
      childItem.NavigateUrl = childView["PageURL"].ToString(); 
      childItem.Target = childView["PageWindow"].ToString(); 
     } 
     menuItem.ChildItems.Add(childItem); 
     AddChildItems(table, childItem, PageInternalLink); 
    } 


} 

HTML

<script type="text/javascript"> 
    $(document).ready(function() { 
     $('#<%=Menu1.ClientID %> ul', '#<%=Menu1.ClientID %> li').removeClass(); 
    }); 
    $(document).ready(function() { 
     $("#dMenuContainer").delay(500).fadeIn(500); 
     $('#smoothmenu1 ul, #smoothmenu1 li').removeClass(); 
    }); 
    ddsmoothmenu.init({ 
     mainmenuid: "<%=Menu1.ClientID %>", //menu DIV id 
     orientation: 'h', //Horizontal or vertical menu: Set to "h" or "v" 
     classname: 'ddsmoothmenu', //class added to menu's outer DIV 
     customtheme: ["", ""], //78AC1B 
     contentsource: "markup" //"markup" or ["container_id", "path_to_menu_file"] 
    }) 
</script> 
... 
    <table align="center" cellpadding="0" cellspacing="0" align="center" > 
     <tr> 
      <td align="center" valign="middle"><div id="smoothmenu1" class="ddsmoothmenu"> 
       <asp:Menu ID="Menu1" runat="server" Orientation="Horizontal" CssClass="ddsmoothmenu" IncludeStyleBlock="False" DisappearAfter="500" > 

       </asp:Menu> 
       </div> 
      </td> 
     </tr> 
    </table> 
+0

知識搜索者,我需要獲取ASP的值菜單不適用於liui元素,因爲我已經看過您使用過的菜單。 –

+0

如果你會檢查我已經修改它使用asp.net菜單.. – Learning

+0

你只需要修改你的代碼,根據你需要和從我提到的鏈接下載Jquery文件和JS文件加上CSS。相信我,我嘗試了與你嘗試相同的事情,但我遇到了各種麻煩。這個菜單腳本是靈活的,可以嵌套到n級.. – Learning

相關問題