I understand this has been discussed before several times on SO, but looks like I have a different scenario.
I have a master page with no <title> tags at all. All the content pages have their title set up in the #Title page directive.
Recently, a requirement came up such that, only for a single page, which is a content page for the master page, the title should be generated dynamically. I use a user control to get the dynamic content and set the page title.
Now as it is known with the behavior of master pages, the single page with dynamic title has an empty <title> tag.
As many other posts on SO suggests, I can set an invisible tag on the master page to fix this, but then the title for all the other pages which has title set as the page directive, goes missing.
May be having a separate master page for the one single page with dynamic title is a workaround, but are there any other solutions for this problem?
For a one single page(MyPage.aspx/MyUserControl.ascx)
MyPage.aspx/MyUserControl.ascx code behind
protected void Page_Load(object sender, EventArgs e)
{
this.Page.Title = "Dynamic";
}
The same code will work on user control's page_load method also, as it is referring this.Page
Here's what I ended up doing. On the Master page, I added a content place holder like below
<head>
<title><asp:ContentPlaceHolder ID="title" runat="server">Default Page Title Here</asp:ContentPlaceHolder></title>
</head>
And on the pages with static title, just put the content inside the title placeholder
<asp:Content ID="Content1" ContentPlaceHolderID="title" runat="server">
XXX - Static Title
</asp:Content>
And on the dynamic title page, called the user control instead of static title like
<asp:Content ID="Content1" ContentPlaceHolderID="title" runat="server">
//call user control here
</asp:Content>
Related
I am being told to re-design MasterPage. My company uses AbleCommerce system and let me tell you its very tricky. I have a different layouts templates created in HTML by AbleCommerece long time ago and now i need to re-design my masterpage.
ex:
OneColumn.html
<div id="wrapper">
[[layout:header]]
<div id="Content">
<div id="MainContent">
[[layout:content]]
</div>
</div>
[[layout:footer]]
</div>
RightSidebar.html
[[layout:header]]
<div id="outerContentWrapper">
<div id="innerContentWrapper">
[[layout:content]]
[[layout:rightsidebar]]
</div>
</div>
<div id="footerbar">[[layout:footer]]</div>
MasterPage:
only one ContentPlaceHolder in MasterPage
<asp:ContentPlaceHolder ID="PageContent" runat="server">
</asp:ContentPlaceHolder>
ContentPage
<cb:ScriptletPart ID="ShowProduct" runat="server" Layout="One Column" Header="Standard Header" Content="Show Product Page" Footer="Standard Footer" Title="Show Product" AllowClose="False" AllowMinimize="false" />
Now, Content Page looks for One Coulmn.html and loads the html then One Column Loads the Standered Header.html page which reference header webuser control and layout loads Show Product Page.html page which reference another set of webuser controls and so on..
Issue: by following this design we now have over 100 html files which references Asp.Net UserControls. So whenever we want to create new page on our website, we have to create .aspx and then include **<cb:ScriptletPart>**, create new set of HTML files and then USerControls.
I want to get rid of this system and Load userControls directly inside the .aspx page, that's easy BUT then i dont know how can i inform masterpage to use One Column Layout OR anyother Layout.
Is there way to tell masterpage from content page to use the layout sepcified by public property in content page. OR anyother suggestion to deal this kind of situation.
To access controls within the master page, there are two approaches:
By means of public properties and methods
If you observed, the content page doesn’t have the header and title tags.
So if we want to modify the title of the content page –and this is obligatory- we need to access the title tag.
Primarily we need to change the title tag so it is accessible from the code page.
Simple, we need to add id and runat attributes as follows:
<title id="sometitle" runat="server"></title>
Then, in the master page, add this property:
public string SomeTitle
{
set
{
sometitle.Text = value;
}
}
And finally within the content page, we add this snippet on the Load event.
MasterPage masterPage = MasterPage)this.Master;
masterPage.mainTitle = "Hello World";
Please Note:
Because the Master property returns a reference of type MasterPage, we need to cast it to MasterPage type. We can avoid this by adding the #MasterType directive in the content page as follows:
<%# MasterType TypeName=" MasterPage " %>
MasterPage myMaster =this.Master;
I hope that helps.
I have a master page 'Master1' and i have used a content place holder 'content1' and loads
pages 'Page1' and 'page2' in the 'content1'. Is there any way to identify which page is loaded to the content place holder whether it is 'Page1' or 'Page2' dynamically.
I think maybe you have misunderstood how master pages work?
In you master page you define the guts of your page that you want all pages to share, like headers and footers etc. The you define a content holder:
<asp:ContentPlaceHolder runat="Server" ID="MainContent">
</asp:ContentPlaceHolder>
The contents of Page1.aspx etc will be injected into that ContentPlaceHolder.
Then in your aspx pages you simply define which master page it should use:
<%# Page Language="C#" MasterPageFile="~/MyMasterPage.Master" ... />
and then define the content that should be injected in to the place holder in the master:
<asp:Content ID="MainContent" ContentPlaceHolderID="MainContent" runat="server">
put all your html in here
</asp:Content>
Note the id used for the ContentPlaceHolderID property, so that it gets injected into the right place - the master page could have several place holders. So both Page1.aspx and Page2.aspx can be loaded in to the place holder, all you have to do is navigate to whichever page you want to display. Nothing needs to be done on the master page.
Try this
ViewContext.RouteData.GetRequiredString("action")
To manage page title on page's,I have a master page where i am taking ContentPlaceHolder.
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /> </title>
and on every page i write
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">Some Title Here
</asp:Content>
Now my client ask me for remove title on all page's and keep it on master page but not remove content place holder code on all page's and master page so that in future if any requirement then we can insert data in to them.
So my problem is without removing them on master page and pages i am not able to put title on master page.So how can i handle this situation?
Thanks Guys.. I got solution
if you want to set part of the title from within the master page. For example, you might want the title of every page to end with a suffix, “ – MySite”.
If you try this (notice the – MySite tacked on):
<%# Master ... %>
<html>
<head runat="server">
<title>
<asp:ContentPlaceHolder ID="titleContent" runat="server" /> - MySite
</title>
</head>
And run the page, you’ll find that the – MySite is not rendered. This appears to be a quirk of the HtmlHead control. This is because the title tag within the HtmlHead control is now itself a control.
The fix is pretty simple. Add your text to a LiteralControl like so.
<%# Master ... %>
<html>
<head runat="server">
<title>
<asp:ContentPlaceHolder ID="titleContent" runat="server" />
<asp:Literalrunat="server" Text=" - MySite" />
</title>
</head>
If you want a good solution to overriding the page title:
Create a class of your own that inherits from the System.Web.Mvc.ViewPage.
Have your view pages inherit from that class:
Write a Page_Load handler in your new class that does something like this:
Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Me.Title = "Company Name | " + Page.Title
End Sub
You also don't need a content place holder to change the title. The <head> tag is already a runat server control. Setting the Page.Title in the page load (or earlier event) work just fine.
You could also put a runat server script tag in your master page to accomplish this task too.
Easiest way:
Move the current ContentPlaceHolder somewhere to your HTML, and wrap it in a <asp:PlaceHolder runat="server" visible="false"/>. When you'll be needing it later on, just move the ContentPlaceHolder back again.
Use the OnPreRender event on the master page to set the title, overriding what has been set on each page.
why not add attribute Visible=false to ContentPlaceHolder of Master Page
I think this is the easiest way to handle your situation.
Happy coding.
Is there a difference between these two scenarios:
(1) Accessing a property on a master page from a regular child
(2) Accessing a property on a master page from a nested master page
I tried to access a textbox in the master page from a content page like this:
TextBox a;
a = (TextBox)Master.FindControl("ayyash"); // Master is declared in MasterType directive
defaultTextbox.Text = a.Text; // defaultTextBox is a textbox control inside default.aspx
it works, but then when I applied the same method on a nested master page:
TextBox a;
a = (TextBox)Master.FindControl("ayyash"); // Master is declared in MasterType directive
myTextBox.Text = a.Text; // myTextBox is a textbox control inside child.master
this does not work, am I missing something? I call both codes inside regulare page_load handler...
I also noticed I cannot set textbox value inside the nested master page from code behind, there is definitely something im missing, what is it?
To shed light on this issue, here is an example:
Nested Master Page:
<%# Master Language="C#" MasterPageFile="MasterPage.master" AutoEventWireup="false" CodeFile="MasterPage2.master.cs" Inherits="MasterPage2" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:textbox id="tx2" runat="server" text="this is two"></asp:textbox>
<asp:contentplaceholder id="newstuff" runat="server"></asp:contentplaceholder>
</asp:Content>
Code behind:
Response.Wrote(tx2.Text);
I get NOTHING, why what did I miss? note that I also tried the recursive find control:
String str = ((TextBox)((Content)FindControl("Content2")).FindControl("tx2")).Text;
still nothing
ContentPlaceHolder cp = (ContentPlaceHolder)this.Master.Master.FindControl("ContentPlaceHolder1");
//base content place holder id
Label objLabel3 = (Label)cp.FindControl("lblNested");
//lblNested is id in nested master page
I read few things here:
http://www.odetocode.com/Articles/450.aspx
and found out that the nested page in the middle never calls Page_Load! instead, it fires a load event that you can catch to set whatever fields, so the answer was in: on nested page do the following:
protected override void OnLoad(EventArgs e)
{
myTextBox.Text = "anything";
base.OnLoad(e);
}
This should work without any problems, so something else must be wrong. I just tried it inside a simple test project and I have no problems finding a control on the master page in both cases.
I would check (again) if you refer to the correct master page inside your nested master page. What you could also check is the runtime type of the Master property inside your nested master page. It should be the type of your master page.
EDIT: I thought the issue was about finding a control in the root master page from a nested master page and this should work without any problems. For finding a control inside a content placeholder in a nested master page, take a look at the following forum post.
You can have absolute control of your content in both master page and nested page from your content page using the directives:
<%# MasterType VirtualPath="your_master.master" %>
<%# Reference VirtualPath="~/your_master.master" %>
See the excellent article from K. Scott Allen in Ode To Code
What is prefered way of setting html title (in head) for view when using master pages?
One way is by using Page.Title in .aspx file, but that requires in master page which can mess with HTML code. So, lets assume no server side controls, only pure html. Any better ideas?
UPDATE: I would like to set title in view NOT in the controller or model.
In our master pages, we created both an "init" ContentPlaceHolder, and a "title" ContentPlaceHolder. If someone wants to programatically set Page.Title, they can set it in CSharp in the init placeholder, or they can override the "title" placeholder using tags.
Master Page
<asp:ContentPlaceHolder id="init" runat="server"></asp:ContentPlaceHolder>
<head runat="server">
<asp:ContentPlaceHolder ID="title" runat="server">
<title><%=this.Page.Title%></title>
</asp:ContentPlaceHolder>
</head>
View Page
Could either override the entire "title" content placeholder:
<asp:Content ID="Content1" ContentPlaceHolderID="title" runat="server">
<title>Home Page</title>
</asp:Content>
or programatically set the page title.
<asp:Content ID="Content1" ContentPlaceHolderID="init" runat="server">
<%this.Title = "Home Page";%>
</asp:Content>
Make sure you remove the Title="" from the Page directive at the top, or you won't be able to programatically change Page.Title.
I see a lot of people that use the <%= ViewData["Title"] %> option.
I suppose you could also insert a ContentPlaceHolder named Title and then just use that on your page, but in all the MVC examples I've seen, they use the first option.
When I create a new MVC project it has files in there and uses a master page. Looking at that it seems it passes the title to the ViewData as ViewData["Title"] and in the master page, in the <head> there is a script block that outputs ViewData["Title"].
I ended up using a code-behind file to implement Page.Title="..." in the Page_Load() method.
I didn't like doing this, however attempts to implement the change directly in the .aspx page did not work, as it resulted in two <title> tags being present, the one I generated, and the one generated by the Master file the page inherited from.
Ideally, my page code should have overridden the master file's <title> value, but I guess this is just one of those quirks that ASP.Net MVC still has, and one that may already be fixed in a newer version of the ASP.Net MVC Framework (we're still on ASP.Net MVC Beta)
You could do this in your Master Page:
<title>
<%:MyTitle + " :: " %>
<asp:ContentPlaceHolder ID="TitleContent" runat="server">
</asp:ContentPlaceHolder>
</title>
where MyTitle = some value from your web.config or hard text like "My Web"
Now in the view pages (Index for example):
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%:"My Home Page"%>
Now when you browse your home page, the title would be "My Web :: My Home Page".
I have a base view class that sets the page title from a resource file. Works pretty good for me.
I created a class called Application with a Title property (using get/set):
public static class Application
{
static string title;
public static string Title
{
get { return title; }
set { title = value; }
}
}
I then set the property on the Page_Load event for each page:
Application.Title = "Silly Application";
then i just reference that property on the master page:
<div id="divApplicationTitle">
<asp:HyperLink runat="server" NavigateUrl="~/Default.aspx"><asp:Image ID="imgApplicationImage" runat="server" SkinID="skinApplicationLogo" /><%=Application.Title%></asp:HyperLink>
</div>
There is a Title property of the #Page directive for content pages.
For ASP.NET content pages just add Title="" in the <%# %> Placeholder.
We ended up with
<head runat=server visible=false>
in master page.
This way we can read from Page.Title (Page.Title requires head element to exist, otherwise it throws an exception, checked that with reflector). We then use our own head element - MVC way.
You could always use javascript in your view page:
<script type="text/javascript>
document.title = "Hello World";
</script>