Does a MasterPage know what page is being displayed? - asp.net

When I navigate on a website utilizing MasterPages, does the application know what page I am on? If so, does it store it in an object I can access?
The reason I am asking is so I can replace this:
//masterpage
<div id="nav_main">
<ul><asp:ContentPlaceHolder ID="navigation" runat="server">
</asp:ContentPlaceHolder></ul>
</div>
//content page(s)
<asp:Content ContentPlaceHolderID="navigation" ID="theNav" runat="server">
<li>Home</li>
<li id="current">FAQ</li>
<li>Videos</li>
<li>Button 4</li>
<li>Button 5</li>
</asp:Content>
With a more elegant solution for the navigation, which highlights the link to the page by having the list item's ID set to "current". Currently each page recreates the navigation with its respective link's ID set to current.

I'd concur with Chris: use a control to handle display of this menu and make it aware of what link should be highlighted. Here's a method I use regularly. It may become more complex if you've got multiple pages that would need the same link styled differently, but you get the idea.
Dim thisURL As String = Request.Url.Segments(Request.Url.Segments.Count - 1)
Select Cast thisUrl
Case "MenuItem1.aspx"
lnkMenu1.CssClass = "Current"
Case "MenuItem2.aspx"
lnkMenu2.CssClass = "Current"
End Select

To get the current request URL from within the master page you would do:
string s = this.Page.Request.FilePath; // "/Default.aspx"
I also recommend moving your navigation into the master page instead of the content page. This will make it easier to maintain / access.

Yes, Use the below code in your master file. It will give you the content page name.
Page.ToString().Replace("ASP.","").Replace("_",".")

Alternatively you can search for page title if you have set an specific title to the child page instead of masterpage try:
this.Page.Title
Hope it helps.

this is in C#
string thisURL = Request.Url.Segments[Request.Url.Segments.Length - 1];
if (thisURL.ToLower()== "default.aspx") li1.Attributes.Add("class","yekan active");
if (thisURL.ToLower() == "experts.aspx") li2.Attributes.Add("class", "yekan active");

You should be able to get the page by accessing the Page property. IE:
string type = this.Page.GetType().Name.ToString();

You'd probably just use one of the Request path from within the master page to set the current. I'd probably also have a property on the master page to override it, so that pages without links or something could set it to something reasonable.

It worked for me this way - Thanks Jared
This is what I did to get our nav menu to highlight the current menu item for the page that we are viewing. The code is in the master page.
You basically get the filepath (Jared's way)
We use the "~" in our links so I had to strip that out.
Iterate the menuItems collection of the Menu control.
Compare the navigateUrl property.
(I'm not the best coder and even worse at explaining - but it works and I was quite chuffed with it!)
protected void HighlightSelectedMenuItem()
{
string s = this.Page.Request.FilePath; // "/Default.aspx"
string nav;
if (s.Contains("~"))
{
s = s.Remove(s.IndexOf("~"), 1);
}
foreach (MenuItem item in navMenu.Items)
{
if (item.NavigateUrl.Contains("~"))
{
nav = item.NavigateUrl.Remove(item.NavigateUrl.IndexOf("~"), 1);
if (s == nav)
{
item.Selected = true;
}
}
}
}

string s = this.Page.GetType().FullName;
string[] array = s.Split('_');
int count = array.Count<String>();
string currentPage = array[count - 2];

The navigation control, not the master page, should be in charge of what page is currently highlighted.
Either the page that is loaded should notify the navigation item who it is, or the nav control itself should keep track of it.
The point is that master pages are supposed to simply be a holder that content is displayed in. They aren't supposed to control anything.

try
this.Page.Master
It will get you the master page of the current page.

There's also the Request.RawURL

Related

How can I add a random number to an ASP.NET menu item url on each click

One step to prevent caching (in addition to adding the appropriate headers etc..) is to add a random number to the end of my URLs.
I'm using an ASP.NET menu and would like to add a random number to each menu item's navigate URL as it is clicked.
I can do this in the MenuItemDataBound event, but haven't had much luck doing the same with the MenuItemClicked Event.
Answer (can't answer my own question for 8 hours, and I don't have time to wait that long so here's my server side solution.)
To do this server side, I've had to remove the sitemap and the databinding from the menu.
I simply added all of the items from the sitemap as menuitems to the items collection in the menu markup removing the url property. The key here is removing the url property.
<asp:menu>
<items>
<asp:menuitem Text="Home" ToolTip="Go Home" Selectable="True" />
</items>
</asp:menu>
Then in your code behind you can handle the MenuItemClicked event (which should now fire, because there is no longer a navigateurl in the markup).
In the MenuItemClicked event codebehind I simply do the following:
string TimeStamp = DateTime.Now.ToString("yyyyMMddHHmmssfffffff");
// get iframe control - must have 'runat=server' attribute
HTMLControl display = CType(this.FindControl("display"), HTMLControl);
// dispatch menuitem
switch (e.item.valuepath)
{
case "Home":
display.attributes("src") = "home.aspx?=" + TimeStamp()
break;
.
.
.
}
This is the server side solution with an iframe.
I don't know if you're considering client-side URL manipulation as an option, but running this little bit of JavaScript on each page load would give you the behavior you're looking for by appending a timestamp to each of the links. You can modify it to target links in a specific area/div of the site, but this example will change them all:
<!-- include the jQuery library -->
<script type="text/javascript">
$(function(){
var time = new Date().getTime();
$('a').each(function() {
var append = (this.href.indexOf('?') > -1 ? '&' : '?');
$(this).attr('href', this.href + append + 't=' + time.toString());
});
});
</script>
Since every time the page loads the timestamp will be different, you should always get a unique set of links.
EDIT Here's a working jsFiddle demoing the behavior: http://jsfiddle.net/2HzqU/2/
I don't think that's the best solution. Have you tried using something like this:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

Why arent the "selected" classes not being set for ASP Menu control?

I'm a frontend developer working with a seemingly incompetant .NET dev that cant seem to resolve why the ASP Menu control is not showing the selected menu item. The .NET developer sent me the following code. Is there some rules missing here that are need to enable the CSS?
Thanks in advance
Controller config
<asp:Menu ID="mnuMaster"
runat="server"
DataSourceID="sitemapMaster"
StaticDisplayLevels="1"
MaximumDynamicDisplayLevels="0"
Orientation="Horizontal"
StaticEnableDefaultPopOutImage="False"
CssSelectorClass="TopMainMenu" onmenuitemdatabound="mnuMaster_MenuItemDataBound"
StaticBottomSeparatorImageUrl="~/App_Themes/PCTools/Images/top_menu_separator.gif"
></asp:Menu>
CSS selected classes
.TopMainMenu .AspNet-Menu li a:active, .TopMainMenu li.AspNet-Menu-Selected a,.TopMainMenu li.AspNet-Menu-ChildSelected a,.TopMainMenu li.AspNet-Menu-ParentSelected a {
background:url(Images/navbg.gif) repeat-x 0 -86px;
}
We normally use a standard UL group in ordinary HTML that a designer provides and then make them into HTML Server Tags.
There may be other solutions but the solution we usually do is this.
First each top level menu item needs an ID.
If the menu is on a masterpage (im going to assume it is)
in the masterpage code behind you can place code like this.
//Discover currently navigated page TYPE
if (this.Page is `pagetype of the current page`)
//add a CSS class to the top level menu item
miFirstMenuItem.Attributes["class"] += " highlightedMenuItemCSSClass";
Then the HTML Output would append an additional CSS class to that menu item which you apply your specific style
Heres a real life example
Node you would have to change the type in the SetActiveTab method to the correct type for the MenuItem
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
bool homeVisited = Page is Default;
bool productsVisited = Page is Products_List;
bool demoVisited = Page is Demonstrations;
bool contactVisited = Page is Contact;
if (homeVisited)
SetActivePage(hlHome, ButtonSide.Left);
if (productsVisited)
SetActivePage(hlProducts, ButtonSide.Middle);
if (demoVisited)
SetActivePage(hlDemo, ButtonSide.Middle);
if (contactVisited)
SetActivePage(hlContact, ButtonSide.Right);
}
}
This shows a different way than I described above but you can replace it with link.Attributes["class"] += " cssClass"; Notice the space after the first ".
Also ButtonSide is an enum I added since all the middle menuitems would have the same CSS class in my particular case and left and right ones as well.
private void SetActivePage(HyperLink link, ButtonSide side)
{
if (side == ButtonSide.Left)
link.CssClass = "currentleft";
if (side == ButtonSide.Middle)
link.CssClass = "currentmiddle";
if (side == ButtonSide.Right)
link.CssClass = "currentright";
}
There seems to be a bug in VS201 / .Net4 where the CSS classnames you specify in de asp.menu properties StaticSelectedStyle & DynamicSelectedStyle are ignored. The menu always uses classname "selected".

Problem regarding master pages

I have a simple master page (master.aspx), which has 3 link buttons namely HomeLBTn-which redirects the users to home.aspx, LoginLBtn-to login.aspx, RegisterLBtn-to Register.aspx
Every page in my project inherits the master page. And home.aspx also inherits the master.aspx, but i don't want the home.aspx to inherit the HomeLBtn, I want it to inherit the remaining 2 LBtn's, but not the HomeLBtn. How can i incorporate this condition into Home.aspx
Please help me
Thanks in anticipation
One way would be to find the control in the MasterPage and set its visibility to false:
Page.Master.FindControl("HomeLBtn").Visible = False
This would be done in the Page_Load (or some other lifecycle event) on the page that shouldn't show the Home button.
In master.aspx, define Register and Login link buttons, and a content placeholder for where the Home button would go. Then have Home.aspx inherit master.aspx. Then create a 2nd master page (master2.aspx) that inherits from master.aspx. In master2, add the Home link button in the content placeholder, and have your other pages inherit from master2.
You can do something like this in the master page ( Check what the child page is )
//If the child page is viewing an order then disable the new request button
if (this.ContentPlaceHolder1.Page is OrderView)
{
base.RemoveMenuItem("New Request", mnuSettings);
}
Note: base.RemoveMenuItem is a method of my base page
http://wraithnath.blogspot.com/2010/09/how-to-hide-show-controls-on-master.html
Another option would be to add a property to the child page and master page and use session data to hide and show buttons.
eg. in Child Page:
protected MyCustomMasterPage CustomMasterPage
{
get
{
return this.Master as MyCustomMasterPage;
}
}
In your master page you could have a session variable you can set to hide and show the buttons
public bool HomeVisible
{
get
{
return (bool) Session["HomeVisible"];
}
set
{
Session["HomeVisible"] = value;
}
}
You would then check the HomeVisible property when loading the master page to show / hide the button. You can then set this from the child page.
this.MyCustomMasterPage.HomeVisible = false;
Maybe not the best ways but they work

Using SiteMapPath to create a dynamic page title?

I currently use SiteMapPath to generate a breadcrumb for my ASP.net 3.5 (vb.net) pages and it works great.
Now I am trying to figure out how I might be able to use the same control to build a dynamic page title (in the tag). I want a reverse path listed, but the SiteMapPath control includes links and bunch of styling spans. Is there any way to remove all of that, and just get a plain path with separators?
For example, Let's say we are on the "Press Releases" page inside of the "About" section of my site.
The breadcrumb shows up as:
Home > About > Press Releases
I want to have the page title be:
Press Releases - About - Company Name
So I need it to reverse the order, drop all spans, links and styling (since this is inside the tag) and drop the root node "Home" and then add the company name to the end. Since my menu nav and breadrumbs are all driven from the sitemap file, I thought it would make sense to try to make the title do the same.
Any thoughts? Thanks.
The best way to achieve your desired output is to ignore the SitePath control, and instead use the SiteMap's SiteMapNode's collection. The server parses the web.sitemap into a collection of SiteMapNodes and wires up the SiteMap.CurrentNode by finding a node that matches the current page's URL. Each SiteMapNode has a ParentNode property. Here is the reference page on MSDN.
So, all you need to do is check if the CurrentNode has a parent, if it does you add the ParentNode's title to the CurrentNode's title and keep going until you reach the RootNode (where you substitute your company name for the root node's title).
Below is a quick solution; it could go in the MasterPage if you are using one. I'm not sure your language, but this should be easy to rewrite in VB.Net. I gave it a simple test and it seemed to work.
You can customize the characters that separate the page titles.
protected void Page_Load(object sender, EventArgs e)
{
Page.Title = SiteMapTitle(SiteMap.CurrentNode, "", " - ");
}
private string GetNodeTitle(SiteMapNode oNode)
{
if (oNode == SiteMap.RootNode)
return "Company Name";
else
return oNode.Title;
}
private string SiteMapTitle(SiteMapNode oNode, string szTitle, string szItemSeparator)
{
if (szTitle != string.Empty)
szTitle = szTitle + szItemSeparator + GetNodeTitle(oNode);
else
szTitle = GetNodeTitle(oNode);
if (oNode.ParentNode != null)
szTitle = SiteMapTitle(oNode.ParentNode, szTitle, szItemSeparator);
return szTitle;
}
Hope that helps...

Client Callbacks With Master Pages

I'm following this example: http://msdn.microsoft.com/en-us/library/ms178210.aspx
And I can get it to work with just a single page and a code behind, but when I add a masterpage, the examples doesn't work properly. Within my master page, I have a head content section and a body content section. It's nothing fancy.
How do i do client callbacks with master pages?
A more scalable approach would be to use the following syntax (replace the ResultsSpan with an aspx Panel too)...
function LookUpStock()
{
var lb = document.getElementById('<%=ListBox1.ClientID%>');
var product = lb.options[lb.selectedIndex].text;
CallServer(product, "");
}
function ReceiveServerData(rValue)
{
document.getElementById('<%=ResultsSpan.ClientID%>').innerHTML = rValue;
}
This way, if the name (or actual page) of the MasterPage changes the code will still work.
Basically the ASP.NET process parses the page and replaces the <%=%> directives with the correct name of the control on the client.
This approach will also work if you have nested controls. In your example, if you had a control nested inside another panel the rendered id could look something like MASTERPAGEPREFIX_CONTAINERCONTOLNAME_ListBox1 and then your work around would fail.
As a general principle its normally considered a bad idea to "hard code" client side ids in your markup - let the ASP.NET process handle it for you
I got it to work.
Be sure that you amend this code to account for the MasterPage contentId prefix:
function LookUpStock()
{
var lb = document.getElementById("MASTERPAGEPREFIX_" + "ListBox1");
var product = lb.options[lb.selectedIndex].text;
CallServer(product, "");
}
function ReceiveServerData(rValue)
{
document.getElementById("MASTERPAGEPREFIX_" + "ResultsSpan").innerHTML = rValue;
}

Resources