Accessing top master page properties in a nested master page code behind - c#

I have a nested master page that has its own master page. The parent master page has a property defined in its code behind.
Public ReadOnly Property SelectedPage() As String
Get
Return _selectedPage
End Get
End Property
How can I reference the parent master page's property from within either the child master page's code behind Page_Load or aspx template page?

VB.Net:
DirectCast(Master, MyMastPageType).SelectedPage
C#:
((MyMastPageType)Master).SelectedPage
http://msdn.microsoft.com/en-us/library/system.web.ui.masterpage.master.aspx

protected void Page_Load(object sender, EventArgs e)
{
MyDemoMaster m = Master as MyDemoMaster;
m.MyProperty = "My button text";
}
See:
How to access controls inside a
nested master page?
The right way of accessing Master
page properties from a child page

Like this:
DirectCast(MyMastPageType, Master).SelectedPage

Here is how I use
MasterPage tmp = this.Master;
while (tmp.Master != null)
{
tmp = tmp.Master;
}

Related

Reading User control property inside Nested Master pages in Content page

I have a user control which is in the root master page. The content page connects to this root master page via nested master page
root.master>apps.master>content.aspx
the user control in the root.master has a drop downlist that sets a property when the dropdownlist selection is changed.
I need to access this user control property in the content page.
any help is appreciated
user control property
private string _userCurrentCity = string.Empty;
public string userCurrentCity
{
get { return _userCurrentCity; }
set { _userCurrentCity = value; }
}
protected void ddl_City_SelectedIndexChanged(object sender, EventArgs e)
{
string CurrentCity = "";
CurrentCity = ddl_City.SelectedItem.Text;
lbl_CurrentCity.Text = CurrentCity;
HiddenField_CityID.Value = ddl_City.SelectedValue;
UpdatePanel2.Update();
userCurrentCity = CurrentCity;//this sets the usercontrol property
}
in my content page
UserControl cnt = this.Master.Master.FindControl("Change1") as UserControl;
lbl_Result.Text = cnt.userCurrentCity;
is this correct, i set the userCurrentCity property in the ddl selected change event. Your code looks logical but it is not working.
You need some code like this in code behind:
UserControl cnt = this.Master.FindControl("IDOfTheUserControl") as UserControl
after that:
cnt.Property //to access the wanted property.
EDIT: I don't understand yhat you have nested master pages.
Try this.Master.Master.FindControl and other things like before.
UserControl cnt = this.Master.Master.FindControl("IDOfTheUserControl") as UserControl

Dynamically change MasterPage and ContentPlaceHolderID of asp content tag?

I have a page which initially inherited from MastePage.master . And I want to use the same page but with different masterpage(MasterPage2.master) at some other place in my project. For that I am using the following code.
private void Page_PreInit(object sender, EventArgs e)
{
if (Request.QueryString["Update"].ToString() == "New")
{
this.MasterPageFile = "MasterPage2.master";
Content con = new Content();
con = (Content)this.FindControl("Content1");
this.Content1.ContentPlaceHolderID = "ContentPlaceHolder2";
}
}
I am also trying to set the asp content tag's ContentPlaceHolderID to ContentPlaceHolder2 which is from MasterPage2.master. Initially it was ContentPlaceHolder1.
But I am getting null value at con = (Content)this.FindControl("Content1");
Thanks
Page internally stores in private '_contentTemplateCollection' hashtable. it uses ContentPlaceHolderID property as key and stores special class (that will be used to build/initialize Content tag) as a value
- so to change ContentPlaceHolderID value (defined within markup) you need to modify this hashtable, remove old entry linked with old Id and add other entry with new Id
- you need to change ContentPlaceHolderId before creating master page otherwise an exception will be thrown in runtime
- best place to change Ids is Page 'preinit' event and if it is better to change Ids before change master page (if you will change master page at runtime)
To change ContentPlaceHolderID of Content tag, you can use following function in Page PreInit event
public static void AssignContentToNewPlaceHoldersWithinPage(Page pPage, string pOldId, string pNewId)
{
if (pPage == null || string.IsNullOrEmpty(pOldId) || string.IsNullOrEmpty(pNewId))
{
return;
}
// Try to get a reference to private hashtable using fasterflect free reflection library in codeplex (http://fasterflect.codeplex.com/)
// you can replace following line with standard reflection APIs
var lTmpObj = pPage.TryGetFieldValue("_contentTemplateCollection");
if (lTmpObj != null && lTmpObj is Hashtable)
{
var _contentTemplateCollection = lTmpObj as Hashtable;
if (_contentTemplateCollection.ContainsKey(pOldId) && !_contentTemplateCollection.ContainsKey(pNewId))
{
var lTemplate = _contentTemplateCollection[pOldId];
_contentTemplateCollection.Add(pNewId, lTemplate);
_contentTemplateCollection.Remove(pOldId);
}
}
}
function parameter are
pPage is reference to page instance contains content tag
pOldId is ContentPlaceHolderId property value in markup - the Id you want to change
pNewId is the new Id you want to use
I hope that my answer will be useful and I am sorry if my English language is not good
You can dynamically change the Master Page at runtime, but you need to use the same ContentPlaceHolder IDs. That way, your pages will work with either Master Page without adding extra code to change the IDs at runtime.
private void Page_PreInit(object sender, EventArgs e)
{
if (Request.QueryString["Update"].ToString() == "New")
{
this.MasterPageFile = "MasterPage2.master";
}
}
You can even test that your page will work with either Master Page in the Visual Studio design/markup view by changing the MasterPageFile in the <% Page %> directive in the .aspx markup.
The Master Page can be changed by overriding OnPreInit.
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
MasterPageFile = "~/MasterPages/MyOther.Master";
}
But for the ContentPlaceHolders I would suggest to create new ContentPlaceHolders with the same name in both of your MasterPages.

Change panel "visible" property on MasterPage from Child pages

I want to show some panel with a label, both located on a MasterPage, from inside it's child pages.. I already did the coding on the MasterPage:
public class MyMaster : MasterPage
{
public void ShowPanel(string pMessage)
{
labelInside.Text = pMessage;
myPanel.visible = true;
}
}
Then I make the calls from child pages:
public void ShowPanel(string pMessage)
{
MyMaster masterPage = this.Master as MyMaster;
masterPage.ShowPanel(pMessage);
}
This "works" ok, but it won't show nothing, since I need the page to be "refreshed" in an "ajax-way" like an UpdatePanel, which I can't use because the Trigger is in another page, right?
I really need this to work.. even if you have another completely different way to do this, I would appreciate.
You must place your panel inside an UpdatePanel(UpdateMode conditional) and in ShowPanel call its Update method.
Have you considered having the masterpage just have a placeholder for the label, but having each child page put its own content label inside that placeholder, which it would then have full control over?
you can subClass your page, and expose a property say.. MyPage.FooVisible
than in your masterPage, you can:
myPage = this.Page as MyPage
if (myPage != null) myPage.FooVisble = false;
in your page you can handle that any way you like,
FooVisible {
set { SomeElement.Visible = value; }
}
pseudo code of course :)

Setting title of a page

I have an ASP.NET application that uses a master page configuration. What I'd like to do is two things.
How can I programmically set the title in the child page (as in the text in the <title></title> tags? And,
If the child page does not set the title, I'd like the master page to automatically detect this and set a default title.
Any help would be appreciated.
you can have your pages inherit from a custom page
public abstract class CustomPage : Page
{
public virtual string PageTitle {get{return String.Empty;}}
}
Then, in your MasterPage's Page_Load, do ( can't remember if MasterPage.Title exists or if you'll have to do Page.Title, which will work since both objects are Page objects):
if(Page is CustomPage) {
this.Page.Title = ((CustomPage)Page).PageTitle;
} else {
this.Page.Title = "Default Title";
}
Then, when you create a Page, for instance a CustomerManager page:
public partial class CustomerManager : CustomPage
{
public override string PageTitle { get{return "Customer Manager"; }}
}
This way, your MasterPage isn't 100% tied to using CustomPage (creating normal Pages won't throw an error). And, if you use CustomPage objects, you're all set!
What I do is basically the same as Jim Schubert's. I do make one small change though, in the MasterPage's PageLoad, i would do a conditional check, something like the following:
if(Page is CustomPage) {
var cp = (CustomPage)Page;
this.Title = (String.IsNullOrEmpty(cp.PageTitle)) ?
"Master's Default Title" :
cp.PageTitle;
}
This then addresses point 2 of you question, so that your custom pages need not specify a title, but can just return String.Empty.
(Forgive if the syntax isn't exactly right, VB is my native language.)
For your first question,This is the one you are looking for http://www.devasp.net/net/articles/display/852.html and
For your second question, http://delphi.about.com/cs/adptips2004/a/bltip0304_2.htm
In the Master page markup, do this:
<head runat="server" id="hd">
<title></title>
</head>
Then, in code behind (assuming AutoEventWireup="false"):
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (String.IsNullOrEmpty(this.mhd.Title))
this.hd.Title = "Master Title";
}
Then in your page you can either set the title declaratively:
<%# Page Title="Page Title" . . . %>
or programmatically:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.Title = "Page Title";
}
for your 1st question shouldnt:
Protected void Page_Load(object sender, EventArgs e)
{
Page.Title = "Title";
}
for each child page ,Do the trick?
you can add a contenttemplate at the header of the masterpage then add a contentplaceholder at the aspx pages inheriting from the masterpage, then in the pageload of the aspx you can set the title :
page.title = "my title"
to answer the second part, you can simply put the default title in the tag at the master page, so that if you did not set it programmatically then it will stay the same.

Dynamically adding Content blocks to Masterpage fails after Master.FindControl

I've encountered an odd problem that doesn't make any sense to me. I am trying to dynamically set up MasterPage Content controls on a page. I have it working nicely with the following code:
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
MasterPageFile = "~/MasterPages/Default.master";
string existantContentPlaceHolderID = "ContentPlaceHolder1";
string nonExistantContentPlaceHolderID = "foo";
//Control c = Master.FindControl(existantContentPlaceHolderID);
//Control c1 = Master.FindControl(nonExistantContentPlaceHolderID);
TextBox t = new TextBox
{
Text = "Text"
};
ITemplate iTemplate = new GenericITemplate(container => container.Controls.Add(t));
AddContentTemplate(existantContentPlaceHolderID, iTemplate);
}
public delegate void InstantiateTemplateDelegate(Control container);
public class GenericITemplate : ITemplate
{
private readonly InstantiateTemplateDelegate m_instantiateTemplate;
public void InstantiateIn(Control container)
{
m_instantiateTemplate(container);
}
public GenericITemplate(InstantiateTemplateDelegate instantiateTemplate)
{
m_instantiateTemplate = instantiateTemplate;
}
}
This works great, except I want to be able to double-check that the contentPlaceHolderIDs exist on the MasterPage before calling AddContentTemplate as the Page will throw an error if you add a Content control that points to a non-existing ContentPlaceHolder.
The problem I am having is that in the above example when I call one of the commented Master.FindControl lines, the TextBox no longer renders.
Does anyone have any ideas why this might be... I cannot makes heads or tails of what is going on.
Thanks,
Max
The problem is that AddContentTemplate just records its parameters in a hashtable ready to be combined with the master page instance when it is created. Calling it after the master page has been created won't do anything, and reading the Master property causes the master page to be created.
The best way I can see around this is to create a separate instance of the master page with LoadControl, which you can inspect without affecting the page's own Master property...
MasterPage testMaster = (MasterPage) LoadControl( MasterPageFile );
Control c = testMaster.FindControl(existantContentPlaceHolderID);
There's some overhead in creating a second instance, but it's not immediately obvious to me whether it will be worth worrying about.

Categories

Resources