maestras - Obtener elementos de menú de la base de datos en asp.net
menu responsive asp net (3)
Modifique su código según el ejemplo siguiente. Estoy usando el siguiente menú. Está funcionando Es posible que deba modificar su código según su necesidad
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>
Estoy tratando de obtener los elementos del menú de la base de datos de SQL Server 2008.
He intentado algo como esto cuando busqué en Google y encontré estos tutoriales primero y segundo :
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();
}
}
}
Tengo dos errores de este código:
- Excepción de índice fuera de rango
-
NullReferenceException
fue manejado por el código
He señalado el código que generó el error.
Esta es mi base de datos junto con los encabezados.
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
Tengo solución para cualquier cantidad de niveles en los elementos de menú.
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);
}
}
}
}
Gracias por KnowledgeSeeker y Antonio por sus respuestas.
y la base de datos es así.
Esta es mi base de datos junto con los encabezados.
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
La solución es: establecer los nodos principales dentro de la base de datos.
Ej .: insertar en valores dbo.MenuItems (333, ''SubSubMenuItem8'', NULL, 21)
Esto establecerá el SubSubMenuItem8
como un hijo en el nodo principal SubMenuItem3
Debe ordenar sus datos por ParentID y luego recorrer la tabla y, para cada elemento, buscar elementos principales y agregarlos a sus elementos secundarios, si no encuentra elementos principales para agregarlos a la raíz.
obtener datos :
string sql = "Select * from MenuItems Order By ParentID";
DataTable data = GetTable(sql);
y luego llena el menú:
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);
}
y aquí está el método GetItems que devolverá todos los nodos de árbol, tomado de aquí: https://.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);
}
}
}
}