2009-06-03 8 views
13

ho il seguente menu a mio masterpage:ASP.NET MVC: Masterpage: Come impostare classe CSS sulla voce di menu attiva

<ul id="menu" class="lavaLampBottomStyle"> 
    <li> 
     <%= Html.ActionLink("Employees", "Index", "Employees")%></li> 
    <li> 
     <%= Html.ActionLink("Customer", "Details", "Account")%></li> 
</ul> 

Ho bisogno di un modo per impostare la classe CSS della corrente li attiva a "corrente".

La mia prima ipotesi è di farlo con l'assistenza di javascript.

vorrei includere qualcosa di simile nel masterpage:

$("#menu li a").each(){ 
    if($(this).attr("href") == '<%= *GET CURRENT PAGE* %>'){ 
     $(this).parent("li").addClass("current"); 
    } 
    } 

E 'questo un buon approccio?

Se lo è, come posso ottenere la parte dell'URL corrente come nell'href?

Se non lo è, qual è il tuo suggerimento? :-)

Cordiali saluti, il codice HTML generato che sto cercando:

<ul id="menu" class="lavaLampBottomStyle"> 
    <li> 
     <a href="/KszEmployees/Index">Employees</a></li> 
    <li> 
     <a class="current" href="/">Customer</a></li> 
</ul> 
+0

Che aspetto ha il ciclo jQuery finale? – Picflight

+0

Picflight ... e chiunque lo cerchi, aggiungi quanto segue alla pagina principale;

+0

grazie mille per aver chiesto questa domanda :) hanno il problema molto simile, ha aiutato molto! –

risposta

6

Questo è probabilmente il modo meno intenso di farlo. Se puoi contare sul fatto che gli utenti abbiano javascript abilitato, non vedo nulla di sbagliato in questo, e l'ho fatto io stesso in occasione.

Request.Url è l'oggetto che ti interessa per ottenere la pagina corrente sul lato server. Il suggerimento di usare window.location.href da tvanfosson non è male se vuoi tenerlo interamente sul lato client.

Il vantaggio dell'utilizzo di serveride è che Request.Url ha parti facilmente accessibili dell'URL, come Request.Url.Host, ecc. Per aiutare con le esigenze di mungitura dei collegamenti.

+0

bella modifica. Userò il servery thingy in quanto sembra più impermeabile di windows.location.href –

+0

In realtà non avevo considerato l'utilizzo dell'oggetto Request in fase di rendering poiché stavo lavorando con un plugin sul lato client e ci ho pensato solo da quella prospettiva . Dovrò vedere se questo rende il mio codice di navigazione più pulito. – tvanfosson

+0

Funziona con questo: $ ("# menu li a [href = <% = Request.Url.LocalPath%>]"). Parent ("li"). AddClass ("corrente"); –

9

Estrarre la posizione corrente window.location. Quindi usa un selettore che specifica il valore dell'attributo href per scegliere solo quegli elementi che corrispondono (presumibilmente solo uno).

var currentLocation = window.location.href; 
// probably needs to be massaged to extract just the path so that it works in dev/prod 

$("#menu li a[href$="+currentLocation+"]").addClass("current"); 
+0

Non ha pensato di tenerlo interamente sul lato client. Non è affatto una cattiva idea usare window.location.href. –

+0

bel selettore jQuery, non ci pensavo :-) –

+0

Ma mi chiedo se questo funzionerà con l'url "/" .. –

-2

Questo NON dovrebbe essere fatto con Javascript! Decidere quale pagina si trova è il lavoro del codice lato server, non è un comportamento dell'interfaccia utente.

Avere il menu come controllo utente e passare un valore ad esso per indicare quale parte del menu deve essere evidenziata. Sono front-end persona, non uno sviluppatore .NET, ma qualcosa di simile:

<yourControl:menuControl runat="server" ID="menu" selectedPage="4" /> 
+1

È possibile combinare codice javascript e serveride .. Non ho intenzione di fare un controllo per questo. Inoltre, è asp.net mvc. E nella tua soluzione dovresti includere il menu in ogni pagina? + è difficile modificare gli ordini delle voci di menu. Un sacco di cose che non vanno nella tua soluzione. –

+3

+1 su non farlo con JavaScript -1 per l'utilizzo di un controllo –

+0

Non so. Penso che sia una cosa banale fallire se JS è disabilitato. Perdi un aiuto alla memoria, in sostanza, se fallisce. Non si interrompe la funzionalità. –

15

Se si vuole fare tutto sul lato server, che ho fatto prima. Creazione di un attributo di filtro azione:

public class PageOptionsAttribute : ActionFilterAttribute 
{ 
    public string Title { get; set; } 
    public string Section { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var controller = filterContext.Controller as ControllerBase; 
     if (controller != null) 
     { 
      controller.SetPageSection(this.Section); 
      controller.SetPageTitle(this.Title); 
     } 

     base.OnActionExecuting(filterContext); 
    } 
} 

Ciò richiede due metodi nella mia classe ControllerBase che tutti i miei controllori ereditano da:

public class ControllerBase : Controller 
{ 
    public void SetPageSection(string section) 
    { 
        // use the section defined or the controller name if none 
     ViewData["PageSection"] = section != null ? 
         section : this.RouteData.Values["controller"].ToString(); 
    } 

    public void SetPageTitle(string title) 
    { 
     ViewData["PageTitle"] = title; 
    } 
} 

impostare il titolo e la sezione pagina su voi metodi di controller:

public class HomeController : ControllerBase 
{ 
    [PageOptions(Title="Home Page", Section="Home")] 
    public ActionResult Index() 
    { } 
} 

Quindi chiamo il valore ViewData dalla mia pagina principale (ciò non interferirà con ViewData.Modello):

<body class="<%=ViewData["PageSection"] %>"> 

Poi riferimento tramite CSS, invece di chiamare .Current, dare ogni elemento nav un ID e poi utilizzare la classe corpo in combinazione con tale ID per determinare la pagina corrente.

body.home #HomeNav { /* selected */ } 
body.about #AboutNav { /* selected */ } 
+0

In alternativa, se tutto il tuo ViewModel viene ereditato da un ViewModel di base, puoi aggiungere i puntelli Titolo/Sezione nel tuo viewmodel di base e impostarli quando compili quelli nei tuoi metodi di visualizzazione. Il metodo sopra riportato presuppone che ogni metodo del controller restituisca sempre la stessa vista (o viste simili che condividono una definizione titolo/sezione), che non sempre si applica. –

+0

sembra abbastanza complesso .. Mi piace così :-) Studio questo metodo per progetti futuri, ma a causa della mancanza di tempo userò la soluzione javascript che ho già implementato per ora .. Grazie per lo sforzo, molto appriciato. –

+0

Diventa molto meno banale se i menu sono generati dinamicamente, come ad esempio un CMS. Questo era il punto di vista dal quale ho risposto alla domanda. Se disponi di collegamenti fisici, allora sì, la soluzione è la migliore. –

0

Ho avuto lo stesso problema. Utilizzando le seguenti risposte, sono riuscito a mettere insieme la soluzione di seguito.

https://stackoverflow.com/a/4733394/280972

https://stackoverflow.com/a/5650735/280972

In HtmlHelpers.cs:

public static class HtmlHelpers 
{ 
    public static HtmlString MenuLink(
     this HtmlHelper htmlHelper, 
     string linkText, 
     string actionName, 
     string controllerName 
    ) 
    { 
     var currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action"); 
     var currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller"); 
     var link = htmlHelper.ActionLink(linkText, actionName, controllerName); 
     var prefix = (actionName == currentAction && controllerName == currentController) ? String.Format("<li class=\"current\">") : String.Format("<li>"); 
     const string suffix = "</li>"; 
     return new HtmlString(prefix + link + suffix); 
    } 
} 

Nel layout:

<ul class="nav nav-list"> 
    <li class="nav-header">Statistics</li> 
    @Html.MenuLink("Number of logins", "Logins", "Statistics") 
</ul> 

Si noti che il MenuLink-helper crea sia il li-tag e l'a-tag.

I commenti su questa soluzione sono i benvenuti!

Problemi correlati