My master page contains a list as shown here. What I'd like to do though, is add the "class=active" attribute to the list li thats currently active but I have no idea how to do this. I know that the code goes in the aspx page's page_load event, but no idea how to access the li I need to add the attribute. Please enlighten me. Many thanks.
<div id="menu">
<ul id="nav">
<li class="forcePadding"><img src="css/site-style-images/menu_corner_right.jpg" /></li>
<li id="screenshots">Screenshots</li>
<li id="future">Future</li>
<li id="news">News</li>
<li id="download">Download</li>
<li id="home">Home</li>
<li class="forcePadding"><img src="css/site-style-images/menu_corner_left.jpg" /></li>
</ul>
</div>
In order to access these controls from the server-side, you need to make them runat="server"
<ul id="nav" runat="server">
<li class="forcePadding"><img src="css/site-style-images/menu_corner_right.jpg" /></li>
<li id="screenshots">Screenshots</li>
<li id="future">Future</li>
<li id="news">News</li>
<li id="download">Download</li>
<li id="home">Home</li>
<li class="forcePadding"><img src="css/site-style-images/menu_corner_left.jpg" /></li>
</ul>
in the code-behind:
foreach(Control ctrl in nav.controls)
{
if(!ctrl is HtmlAnchor)
{
string url = ((HtmlAnchor)ctrl).Href;
if(url == GetCurrentPage()) // <-- you'd need to write that
ctrl.Parent.Attributes.Add("class", "active");
}
}
The code below can be used to find a named control anywhere within the control hierarchy:
public static Control FindControlRecursive(Control rootControl, string id)
{
if (rootControl != null)
{
if (rootControl.ID == id)
{
return rootControl;
}
for (int i = 0; i < rootControl.Controls.Count; i++)
{
Control child;
if ((child = FindControlRecursive(rootControl.Controls[i], id)) != null)
{
return child;
}
}
}
return null;
}
So you could do something like:
Control foundControl= FindControlRecursive(Page.Master, "theIdOfTheControlYouWantToFind");
((HtmlControl)foundControl).Attributes.Add("class", "active");
Forgot to mention previously, that you do need runat="server" on any control you want to be able to find in this way =)
Add runat="server" on the li tags in the masterpage then add this to the appropriate page_load event to add the 'active' class to the li in the masterpage
HtmlGenericControl li = HtmlGenericControl)Page.Master.FindControl("screenshots");
li.Attributes.Add("class", "active");
You could register a client script like this:
(set id to the id of the li that you want to set to active)
ClientScript.RegisterStartupScript(this.GetType(), "setActiveLI", "document.getElementById(\""+id+"\").setAttribute(\"class\", \"active\");", true);
This generates a JavaScript call on the page near the bottom after elements have already been rendered.
All the parts have already been provided in previous answers, but to put the whole thing together, you'll need to:
add the runat="server" attribute to the <ul> and <li> elements
add a public method to do the work on the master page that can be called from the pages using the master page
call the method from the Page_Load of the pages
Alternatively you could also add the code to the OnLoad(...) method of the master page, so you don't have to add the method call to the Page_Load on every page.
If they were runat=server you could use the attributes property.
In order to find that particular control it will need to be defined as public (in the generated designer)
Or will need to be wrapped by a public get in the codebehind.
You can expose the li's on the master page to any content pages by wrapping them in properties on the master page:
public GenericHtmlControl Li1
{
get
{
return this.LiWhatever;
}
}
Then on the content page:
MasterPage2 asd = ((MasterPage2)Page.Master).Li1.Attributes.Add("class", "bla");
If i've got that right!
I found a link that works using CSS and involves only changing the body tag's class attribute. This means there's no Javascript and there's no for loops or anything.
#navbar a:hover,
.articles #navbar #articles a,
.topics #navbar #topics a,
.about #navbar #about a,
.contact #navbar #contact a,
.contribute #navbar #contribute a,
.feed #navbar #feed a {
background: url(/pix/navbarlinkbg.gif) top left repeat-x; color: #555;
}
....
<body class="articles" onload="">
<ul id="navbar">
<li id="articles">Articles</li>
<li id="topics">Topics</li>
<li id="about">About</li>
<li id="contact">Contact</li>
<li id="contribute">Contribute</li>
<li id="feed">Feed</li>
</ul>
Read more here
http://www.websiteoptimization.com/speed/tweak/current/
Try this
the great example for future use. i know this thread is old, but for future queries...
http://community.discountasp.net/showthread.php?p=33271
Thanks For the solution.
Mininized code.
Master page control can also find in the child page..
i mean master page contains html contol
and chilld page can find the master page html conrol like this
((HtmlControl)this.Master.FindControl("dpohome1")).Attributes.Add("class", "on");
Simple logic and minimal code, I usually use the following code, especially in dynamic menu. Hope this helps.
Create this method code in the code behind master page
CODE BEHIND (C#)
protected string SetCssClass(string page)
{
return Request.Url.AbsolutePath.ToLower().EndsWith(page.ToLower()) ? "active" : "";
}
In the menu list items you have created call this method passing the page name like this
HTML PAGE (ASPX inline code)
<li id="screenshots" class = "<%= SetCssClass("screenshots.aspx") %>">
Screenshots</li>
<li id="future" class = "<%= SetCssClass("future.aspx") %>">
Future</li>
and so on.
By this method, every time you add a page and link, you don't have to write code in every page. Just when you add the link in the master page, with every <li> invoke the SetCssClass(pagename) method call for setting class and it's done. (you can rename the method as per your ease.
You can use longer codes if you are being paid per lines of code bcoz then this is just one line of code. (lol). Just kidding. Hope it helps.
Note: I am ignoring other parts of the html code, you can include them also, that would work fine.
Related
One of the overloads for Html.RenderPartial allows you to pass in a model. How can you make use of that from _Layout.cshtml?
I have a model prepared with everything I need. I just can't see how to make it accessible to the Layout.
_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<nav>
#{ Html.RenderPartial("pMenu", menu); }
</nav>
...
pMenu.cshtml
The partial view for the menu. Hopefully this makes it clear that the menu is dynamic and really does need a model passed to it.
#model MyApplication.Menu
#foreach (KeyValuePair<string, MyApplication.MenuGroup> group in Model.group)
{
if (group.Key != "default")
{
<div>#group.Key.ToString()</div>
}
<ul>
#foreach (MyApplication.MenuItem item in group.Value.items.Values)
{
<li>
#if (item.isCurrent)
{
<span class="#item.Icon">#item.LinkText</span>
}
else
{
#Html.ActionLink(item.LinkText, item.Action, item.Controller, item.RouteValues, new { #class = #item.Icon })
}
#if (null != item.subItems)
{
<ul class="tree">
#foreach (MyApplication.SubItem subitem in item.subItems)
{
<li>
#if (subitem.isCurrent)
{
<span>#subitem.LinkText</span>
}
else
{
#Html.ActionLink(subitem.LinkText, subitem.Action, subitem.Controller, subitem.RouteValues, null)
}
</li>
}
</ul>
}
</li>
}
</ul>
}
Where is the menu instantiated?
public class MainController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
menu = new Menu(requestContext.RouteData.Values);
Background information
This is an intranet application. It does not have the typical hard-coded menu options of "Home", "About", "Contact". Most of the menu is created from user-maintained database records. The menu is individualised to the user. No two users will have the same menu items. Eg: A manager gets a menu item for each of their staff.
The menu model also handles other factors that make the menu "dynamic" such as:
identifying whether the requested page matches a given menu item (by route data) (for styling)
adding extra menu items based on roles
sometimes adding sub-menus for the current context
This seems similar to #Render partial with a model in Layout View but I think that question went off the rails by referring to session.
Disclaimer: I'm an experienced programmer but relatively new to C# and asp.NET MVC.
ViewData to the rescue.
_Layout.cshtml
#{ Html.RenderPartial("pMenu", ViewData["menu"]); }
MainController
menu = new Menu(requestContext.RouteData.Values);
ViewData["menu"] = menu;
Modifying menu after this point still works. I'm not sure why, but I'll take it.
See also Best way to do global viewdata in an area of my ASP.NET MVC site?
I think you want to render a menu. from my view you should create a helper method for this purpose. If you want to go through this technique and if you are new to create your own tag then following this basic tutorial to get some undestanding : http://www.codeproject.com/Articles/787320/An-Absolute-Beginners-Tutorial-on-HTML-Helpers-and
You could always include a base index view that contains generic things then reference your layout in the page. You somewhat inherit the view and send in model data.
#model Model.MyIndexModel
#{Layout = "~/Views/Shared/Layouts/_SinglePageLayout.cshtml";}
I am creating asp.net web application project.In that I created one master page which having header and footer.In header section there are some links..If i click the link That links goes to their own aspx file..that all aspx files are created by using the master page...how to highlight the every links when we go to that page without affecting the masterpage contents.
This is my code:(the line i put star is the links)
<!-- header start -->
<li>Home</li> *
<li>What We Do</li> *
<li>Our Activities</li> *
<li>Our Projects</li> *
<li>Contact</li> *
<!-- header start -->
Example you have pages: Home.aspx,WhatWeDo.aspx..
Your Menu li0:Home.aspx,li1:WhatWeDo.aspx..
You can use global javascript in master page
if(location.href.indexOf("Home.aspx")>0)setactivecss(0)
else if(location.href.indexOf("WhatWeDo.aspx")>0)setactivecss(1)
to set active css for your select page
You can try your own code with my sugest.
Hope this help
Idea1: Add styles on the particular page with the reference of href link. For example in what.aspx you need to add it like below.
<style>
li.a[href='what.aspx']{background-color:red; color:#fff;}
</style>
Idea2: Add classes for each li.
<li class="default">Home</li>
<li class="what">What We Do</li>
<li class="activity">Our Activities</li>
<li class="projects">Our Projects</li>
<li class="Contact">Contact</li>
Apply the styles for the classes on that particular page. For exmaple in what.aspx you need to add it like below.
<style>
li.what{background-color:red; color:#fff;}
</style>
You could do it with some jQuery
Add the id 'li-home' to your home link list item and give the list an id of 'menu'
<ul id='menu'>
<li id="li-home">Home</li>
Then with jQuery
var path = window.location.pathname;
if (path.trim() == "/") {
//covers the case of the default page since default.aspx will not show
$("#li-home").addClass("Active");
}
else {
var items = $("#menu li");
items.each(function (index, li) {
var menuitem = $(li);
if (path.trim() !== "/" && path.indexOf(menuitem.find("a").attr("href")) > -1) {
$("#li-home").removeClass("Active");
menuitem.addClass("Active");
}
});
}
so i have this button that appears on multiple pages all leading to the parent page. But now - when i reach the parent page i still have the button showing. I want to remove/hide the button when on the parent page.
Is it possible that i could check my current page url and check to see if it the parent page?
<a id="element" href="/Pages/#ViewBag.ElementId" class="btn">
<i>Home</i>
</a>
thinking using an if statement surrounding the tag
If you wanted to do your check in the code behind page, you can always execute the code below during the page load event.
if (Path.GetFileName(Request.Url.LocalPath) == "ParentPage.aspx")
{ element.visible = false; }
else
{ element.visible = true; }
yeah that's what the window.location variable is for see this
When you are in your parent page, what is the ElementId value ?
I assume it can be null, so you may be able to check this value before displaying your button
#if(ViewBag.ElementId != null){
<a id="element" href="/Pages/#ViewBag.ElementId" class="btn">
<i>Home</i>
</a>
}
else { //TODO...
}
It looks like ASP.NET MVC to me.
#if (!Request.Url.AbsolutePath.EndsWith("/i/dont/want/this"))
{
<a id="element" href="/Pages/#ViewBag.ElementId" class="btn">
<i>Home</i>
</a>
}
I want to add something like this in the code behind:
<ul>
<li><a>A</a></li>
</ul>
However, the ListItem of ASP.NET seems to allow text only:
BulletedList UserSubMenuList = new BulletedList();
ListItem EditUserItem = new ListItem("Edit Profile");
Is there other way to add content between <li></li> tag with code behind rather then using HtmlGenericControl?
Front :
<ul id="test" runat="server">
</ul>
Back:
Label label1=new Label();
label1="test";
test.Controls.Add(new LiteralControl("<li>"));
test.Controls.Add(label1);
test.Controls.Add(new LiteralControl("</li>"))
Try this:
BulletedList UserSubMenuList = new BulletedList();
UserSubMenuList.Items.Add(new ListItem(HttpUtility.HtmlEncode(#"Edit Profile"));
Note that you'll be clearing whatever was initially displayed if you do the first line (the constructor).
The Text property is simply the string of text to put in the <li> tags - if it's text (like all HTML markup), it should be able to go there.
In my web app (asp.net C#) I have menus as "All", "Education", "Fun", "Comedy". I want when I select All then it should be displayed as current menu, for which I have a CSS class current.
In case of WebUserControls I can do it easily by passing parameter of current page to select as below:
mywebpage.aspx
<uc:header ID="header1" runat="server" selectedMenu="comedy" />
header.ascx (code (c#))
public string selectedMenu
{
get { return strSelected; }
set { strSelected = value; }
}
header.ascx (html)
<ul>
<li><a href="/all/" title="All Videos" <%if (strSelected == "all"){%>class="current"<%} %>><span>All</span></a></li>
<li><a href="/fun/" title="Fun Videos" <%if (strSelected == "fun"){%>class="current"<%} %>><span>Fun</span></a></li>
<li><a href="/comedy/" title="Comedy Videos" <%if (strSelected == "comedy"){%>class="current"<%} %>><span>Comedy</span></a></li>
</ul>
When I'll pass comedy from my webpage to usercontrol then it will select comedy menu. I want to implement the same kind of functionality in case of master pages, could anyone tell me how to achieve this type of facility for master pages.
One way what I feel is to pass a query string parameter http://example.com/all/?select=all, I'll check on master page_load function if select parameter is "all" or fun or comedy then select corresponding menu. But this is not good, because I don't want to add an extra query string parameter to my URLs.
Please tell me how to solve this issue.
Thanks
You can access master page properties from your content page after casting the master to the correct type:
public class MyMasterPage : MasterPage
{
public string MyMenuProperty { get; set; }
protected void Page_PreRender(object sender, EventArgs e)
{
if (MyMenuProperty == "comedy")
{
/* do your menu stuff */
}
}
}
public class MyContentPage : Page
{
protected void Page_Load(object sender, EventArgs e)
{
var myMaster = Page.Master as MyMasterPage;
if (myMaster != null)
{
myMaster.MyMenuProperty = "comedy";
}
}
One way i have done simular in the past is add this to the page derivatives of any content pages:
<%# MasterType VirtualPath="~/YourMaster.master" %>
Then in the master i exposed this:
private PageTypes currentPageType;
public PageTypes CurrentPageType
{
get { return currentPageType; }
set { currentPageType = value; }
}
On this job this was used so the master knew what type of page it was on and therefore changed a few things, colours, controls etc. So from a contents pageload i did
Master.CurrentPageType = PageTypes.System;
One thing to note however, VS tends to moan about the MasterType derivative until you do a rebuild all.
I'm thinking that maybe a completely different approach might be easier to implement and maintain.
How about you just parse the URL in your header.ascx?
For example:
<li><a href="/all/" title="All Videos" runat="server" class='<%= Request.Url.ToString().Contains("/all/") ? "current" : "" %>' ><span>All</span></a></li>
That way, you won't have to worry about setting properties, accessing/casting master pages etc...
Hai prashant,
I had the same issue a month back and i posted in stack overflow check this one it may help you Find a UnorderedList <UL> control inside a master page from a content page in asp.net