asp.net mvc - net - Mvc Dynamic Menu Poblando texto plano
viewdata asp net mvc (2)
He creado el método recursivo del menú dinámico de nivel N''th que crea un menú.
Como se ve en la imagen de arriba, el contenido se devuelve a ParialView llamado "_Menu.cshtml" y este archivo de Vista parcial está vacío.
y luego hay un _LayoutPage.Cshtml
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
<div>
<input type="text" id="txtSearch" />
<button id="btnSearch">Search</button>
</div>
<div id="Menu">
@{Html.RenderAction("_Menu", "Home"); }
@Html.Partial("_Menu")
</div>
<div>
@RenderBody()
</div>
</div>
</body>
</html>
con éxito pone el resultado en el navegador, pero como un texto simple como he mencionado anteriormente y se puede ver a continuación.
¿Cómo puedo hacer que estos actúen como enlaces, no como texto plano? La ayuda será apreciada. Gracias :)
Tomé una visión un poco más involucrada en este caso.
En el diseño que puse ...
@if (Model != null && Model is Core.Objects.Entities.CMS.Page)
{
@Html.Action("Menu", new MenuOptions { IsRootMenu = true, ForPageId = Model.Id, Depth = 3 })
}
Primero compruebo si el usuario está conectado y, por lo tanto, "en una página administrada", lo cual solo ocurre si el modelo es de un tipo específico "Core.Objects.Entities.CMS.Page".
Luego llamo a @ Html.Action que llama a la siguiente acción secundaria en mi controlador y construyo mis opciones de menú ...
[HttpGet]
[ChildActionOnly]
[Route("~/Menu")]
public ActionResult Menu(MenuOptions options)
{
//TODO: consider other complex menuing scenarios like a popup / tree based structures
// New api calls may be needed to support more complex menuing scenarios
// TODO: figure out how to build these, perhaps with a string builder
var expand = string.Empty;
if (options.Depth > 0)
{
switch (options.Depth)
{
case 1: expand = "?$expand=PageInfo,Pages($expand=PageInfo)"; break;
case 2: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo))"; break;
case 3: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo)))"; break;
case 4: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=Pages($expand=PageInfo))))"; break;
case 5: expand = "?$expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo,Pages($expand=PageInfo)))))"; break;
}
}
var query = options.IsRootMenu
? "Core/Page/MainMenuFor(id=" + options.ForPageId + ")" + expand
: "Core/Page/ChildrenOf(id=" + options.ForPageId + ")" + expand;
var items = Task.Run(() => Api.GetODataCollection<Page>(query)).Result;
return PartialView(new MenuViewModel { Origin = options.ForPageId, Pages = items });
}
En mi caso, esta área necesita un poco de trabajo y probablemente debería reemplazar esa declaración de caso con un código de bucle más inteligente que genere la consulta.
En resumen, todo lo que hace es sacar una jerarquía de objetos de página de mi API OData a la profundidad determinada por mis opciones, ya que los menús tienden a variar, algunos son opciones de un solo nivel, otros van de múltiples niveles, pero yo quería un sistema de menú reutilizable.
Una vez hecho esto, puedo tomar el resultado de OData y construir un modelo para una vista de menú que se parece a esto ...
@model MenuViewModel
@if (Model.Pages != null)
{
<ul class="menu">
@foreach (var p in Model.Pages)
{
Html.RenderPartial("MenuItem", new MenuItemViewModel { Page = p, Origin = Model.Origin });
}
</ul>
}
Las vistas de menú configuran una lista para la raíz y representan un elemento secundario para cada página secundaria, planeo ampliar esta vista en algún momento para cosas como escupir la página principal que podría estar en el resultado de OData que obtuve en el controlador.
Y la última pieza del rompecabezas es la vista del elemento de menú que trata sobre la representación de cada elemento de menú individual ...
@model MenuItemViewModel
<li>
<a href="@Html.Raw("/" + Model.Page.Path)" @CurrentItem(Model.Page)>@Html.PageInfo(Model.Page).Title</a>
@if (Model.Page.Pages != null && Model.Page.Pages.Any())
{
<ul class="submenu">
@foreach (var p in Model.Page.Pages)
{
Html.RenderPartial("MenuItem", new MenuItemViewModel { Page = p, Origin = Model.Origin });
}
</ul>
}
</li>
@functions{
MvcHtmlString CurrentItem(Core.Objects.Entities.CMS.Page p)
{
if (Model.Origin == p.Id) return new MvcHtmlString("class=''selected''");
return null;
}
}
Después de haber hecho todo esto termino con un conjunto de listas anidado, entonces uso CSS para manejar cosas como ventanas emergentes o expandir dinámicamente ect.
Esta funcionalidad no está del todo completa, necesito asegurarme de manejar "marcar el elemento actual" con una clase o algo para poder darle un estilo diferente y hay algunos otros escenarios de menú que me gustaría agregar, pero también he considerado reutilizando esta estructura html de alguna manera para las vistas de árbol pero los árboles pueden ser un poco más involucrados en el largo plazo, pero hacer cosas como colocar una imagen al lado de los elementos del menú parece una buena mejora lógica si es configurable :)
Una última cosa que olvidé poner antes es el modelo de opciones de menú utilizado en la acción del menú en el controlador ...
public class MenuOptions
{
public bool IsRootMenu { get; set; }
public int ForPageId { get; set; }
public int Depth { get; set; }
}
Aunque War resolvió mi consulta anterior. Pero todavía quiero responder a las personas para quienes la respuesta anterior parece compleja. de la manera más fácil posible en MVC para completar el menú de navegación dinámica desde la base de datos.
en Controlador:
public ActionResult Index()
{
Menu menu_ = new Menu();
ViewBag.Menu = menu_.getMenuList();
return View();
}
en _layoutpage.Cshtml
<div id="Menu">
@{ List<WebApplicationMVC.Core.Models.menu> All = ViewBag.Menu;}
<ul>
@foreach (var One in All.Where(m => m.ParentId == 0))
{
List<WebApplicationMVC.Core.Models.menu> Child = All.Where(m => One.id == m.ParentId).ToList();
if (Child.Count > 0)
{
if(One.ActionLink == "Yes")
{
<li>
@Html.ActionLink(One.Name, One.Action, One.Controller)
@SubMenu(One, All)
</li>
}
else
{
<li>
@One.Name;
@SubMenu(One, All)
</li>
}
}
else
{
<li>@Html.ActionLink(One.Name, One.Action, One.Controller)</li>
}
}
</ul>
@helper SubMenu(WebApplicationMVC.Core.Models.menu Object, List<WebApplicationMVC.Core.Models.menu> List)
{
List<WebApplicationMVC.Core.Models.menu> subChilds = (from a in List where Object.id == a.ParentId select a).ToList();
<ul>
@foreach (var subOne in subChilds)
{
List<WebApplicationMVC.Core.Models.menu> InnerChilds = (from a in List where subOne.id == a.ParentId select a).ToList();
if (InnerChilds.Count > 0)
{
if (subOne.ActionLink == "Yes")
{
<li>
@Html.ActionLink(subOne.Name, subOne.Action, subOne.Controller)
@SubMenu(subOne, List)
</li>
}
else
{
<li>
@subOne.Name
@SubMenu(subOne, List)
</li>
}
}
else
{
<li>@Html.ActionLink(subOne.Name, subOne.Action, subOne.Controller)</li>
}
}
</ul>
}
</div>