Nested Masterpages and .FindControl - c#

On one site, I'm only using a single level Masterpage and in a page using that master, I can do this.Master.FindControl("controlName") to access the control. Works fine.
However, using the same code on a site with two masterpage levels. MainMaster and SpecificMaster which has MainMaster as its Master.
So on the page which uses SpecificMaster, FindControl is returning null for the object. The only difference I'm seeing is the nesting of the masterpages.
When I set breakpoint and look at page.Master, it's showing SpecificMaster and SpecificMaster is showing MainMaster as its master correctly, but FindControl is still failing.
When I view source in IE, the control is correctly named, no .NET munging going on.
Any thoughts here?
TIA!

When you're nesting master pages, you'll get an extra container "Content" you need to look through.
As a result, if you're trying to use FindControl from a given child page the usual approach is something to the effect of:
Label myLabel = (Label)this.Master.FindControl("myLabel");
myLabel.Text = "Success!";
Since we have a nested master page, with "myLabel" in the child master, this control will be contained within a content control.
So, this changes the code to:
ContentPlaceHolder ph = (ContentPlaceHolder)this.Master.Master.FindControl("yourContentPane");
Label myLabel = (Label)ph.FindControl("myLabel");
myLabel.Text = "Success!";
and in VB.NET
Dim ph As ContentPlaceHolder = DirectCast(Me.Master.Master.FindControl("yourContentPane"), ContentPlaceHolder)
Dim myLabel As Label = DirectCast(ph.FindControl("myLabel"), Label)
myLabel.Text = "Success!"
The content from the child page is loaded into the first master page control, which is subsequently loaded into the grandparent master page.

have you tried this.Master.Master.FindControl("controlname"); ?

It is working as well for cross-page postback:
ContentPlaceHolder ph = (ContentPlaceHolder)PreviousPage.Master.FindControl("ContentPlaceHolder");
string txt = ((TextBox)(ph.FindControl("UserTextBox"))).Text;

I usually do this:
(TextBox)this.Master.FindControl("ContentplaceHolder1").FindControl("TextBox1");

HyperLink hl = (HyperLink)Master.Master.FindControl("HyperLink3");
This is the easiest way to find controls from the nested master pages.

My scenario was as follows. Not sure if this setup is the correct one, but it allowed me to have master-submaster page setup, and be able to find control.
MasterPage-> SubMasterPage -> ASPX page
MasterPage:
<asp:ContentPlaceHolder ID="MasterPageContentPlaceHolder" runat="server">
</asp:ContentPlaceHolder>
SubMasterPage:
<asp:Content ID="ModuleMainContent" ContentPlaceHolderID="MasterPageContentPlaceHolder" runat="server">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
ASPX.cs:
ContentPlaceHolder MainContent = (ContentPlaceHolder)this.Master.Master.FindControl("MasterPageContentPlaceHolder").FindControl("MainContent");
TextBox var_type = MainContent.FindControl("air") as TextBox;

try this
string txt = ((TextBox)this.Master.FindControl("ContentIDName").FindControl("TextBox1")).Text;

Related

Update ContentPlaceHolder with Ajax?

Say i have a MasterPage and two subpages, that are included through the ContentPlaceHolder.
Would it possible in AJAX to update the ContentPlaceHolder to change from 1 subpage to another?
And if so, are there any problems that i may encounter by using this type of interface?
You can't use ContentPlaceHolder control, since it will not be rendered in your page.
Please use div runat="server" and use div id to load the ajax content
All the scripts in the page will work fine loaded via ajax. There are few scenarios it will break/conflict with the parent page script. In that case, you can use iframe and set a src attribute

Change label in masterpage in just one content page

How do I define a label in a masterpage from inside one control page, withouth losing it when I navigate to another control page? I know that I can use this code and it works:
(Master.FindControl("myControl") as Label).Text = "someNewContent";
But I have to define this on every page to keep the same content in the label. Is there a easier/shorter way to define this piece of code only one time in the whole program? Thanks in advance.
I think I get the gist of what you're asking:
Firstly, I would strongly type the master page, in your content page just below the #Page directive, by using the #MasterType directive:
<%# MasterType TypeName="*fully qualified type of your master page*" %>
Next, place a public property on your master page, like so:
public string MyText
{
set { this.ViewState["TheText"]; }
}
In your content page (during the Page_Init, for instance) you can add:
this.Master.MyText = "Whatever you want to say!";
Then load your master pages control text property in the Page_Load event:
protected void Page_Load(object sender, EventArgs e)
{
this.myControl.Text = Convert.ToString(this.ViewState["TheText"]);
}
This won't persist from content page to content page because each content page instantiates a new instance of the master page. In that case, put whatever text you want to persist in Session, then read it in the mater pages Page_Load event.
Hope this answers your question.

Asp.Net: User controls, javascripts and javascript libraries

I have a user control which requires Javascript/Jquery per control. It is actually a control to represent data graphically using some javascript library. As a norm all my javascript links are located at the bottom of the page in the Master Page. This implies I cannot write any javascript in the control because it will appear before any of its dependencies. Also, Even if the script is located at the bottom of the page, it only works for the first control. Has anyone encountered similar challenges? I'm looking for a way out. Thanks
You can register client scripts from code-behind.
var clientScriptManager = Page.ClientScript;
if(!clientScriptManager.IsStartupScriptRegistered("a_key")) { //If multiple control instances are present on the page, register scripts only once
RegisterStartupScript(Page.GetType(), "a_key", "<script src=\"/js/a_library.js\"></script>"));
}
RegisterStartupScript will add <script> tag at the very bottom of the page, before </body> closing tag.
I had a similar issue "updating" a legacy site that had tons of inline JS... so I also ran into issues when I moved jQuery and other scripts to the bottom of the page. I solved it by adding a new ContentPlaceHolder to the master page, underneath the other script references:
<asp:ContentPlaceHolder ID="ScriptsPlace" runat="server"></asp:ContentPlaceHolder>
</body>
Then went through the pages and moved all the inline JS into a content block for ScriptsPlace.
<asp:Content ID="Content5" ContentPlaceHolderID="ScriptsPlace" runat="server">
<script>
//some awesome JS
</script>
</asp:Content>
Although this doesn't work for user controls... so I made a somewhat hacky solution that essentially involved putting all of the user controls JS into a div named _jsDiv and then from the code-behind moving that div into the placeholder (I'm not fond of RegisterStartupScript and it's not practical for a lot of code).
Since I did this in multiple controls, I did these steps:
Step 1 - Make a custom user control, ScriptMoverUserControl.cs:
public class ScriptMoverUserControl : System.Web.UI.UserControl
{
protected void Page_PreRender(object sender, EventArgs e)
{
ContentPlaceHolder c = Page.Master.FindControl("ScriptsPlace") as ContentPlaceHolder;
HtmlGenericControl jsDiv = this.FindControl("_jsDiv") as HtmlGenericControl;
if (c != null && jsDiv != null)
{
jsDiv.ID = Guid.NewGuid().ToString(); //change the ID to avoid ID conflicts if more than one control on page is using this.
c.Controls.Add(jsDiv);
}
}
}
Step 2 - Make your user control use this new control class:
It will inherit ScriptMoverUserControl instead of System.Web.UI.UserControl
public partial class SomeGreatControl : ScriptMoverUserControl
Step 3 - Dump your user control scripts in a div named _jsDiv:
<div id="_jsDiv" runat="server">
<script>
//some awesome JS
</script>
</div>
It's been working fine for me, but if anyone knows a better/cleaner way, I'd like to know!

Update label of MasterPage from content page when there is no ScriptManager in master page

I had not used ScriptManager on my MasterPage as it was not required when I started developing the project, so I have an individual ScriptManager and UpdatePanel for each content page.
In the MasterPage now I've added a label which shows the current system time, and my client wants it to change asynchronously and give a live clock feeling. Can I change the label text in the master page from the content page using Timer? So far I'm unable to achieve this, as I can't use an UpdatePanel also in the MasterPage because there is no ScriptManager tag.
So is there a way to achieve this?
Thanks # Yuriy Rozhovetskiy, From your suggestion i had created a simple javascript and called that javascript on Master page body on load and its working fine. Please find code below which may help to some one who also have same requirement:-
Javascript Function:-
<script type="text/jscript">
function clock(){
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
$('#clock').html(h+"<span class='colon'>:</span>"+m+"<span class='colon'>:</span>"+s);
// $('.colon').fadeTo(1000, .2);
setTimeout(clock, 1000);
}
<body onload="clock()">
Added this to display clock on master page.
<span id="clock" style="font-family:Calibri;color:White;font-weight:bold;font-size:1.3em;"></span>

Can I change the text of a label in a masterpage when loading a content page?

I have a label in a master page (sample.master) called lblHeading.
I want to dynamically change the text of the label when I load the content page.
I need to do this because I want to change the heading to something meaningful but only after I know about the content of the page.
Is this possible?
yes, you can in this very simple way........
((Label)Master.FindControl("lblHeading")).Text = "your new text";
Yes.
You want to create a strongly-type master page and you can then access it's properties from your content page during Page_Load or wherever else.
Yes, it is possible. MasterPage behaves just like UserControl in your page.
Possible steps to implement this:
Create a property or method on the MasterPage that enables you to make changes to the Label. E.g.:
public void ChangeLabel(string label) {
lblHeading.Text = label;
}
From your Page, get the reference to the MasterPage by using the Page.Master property.
Call the method defined in step 1 to change the MasterPage contents.
Additional info: You may need to cast Page.Master into your MasterPage type, try Coding the Wheel's link for instructions on how to do that.
Do as stated above. Then, e.g., from your page do this (master page has label with ID="Label_welcome"):
Label mpLabel = (Label)Page.Master.FindControl("Label_welcome");
if (mpLabel != null)
{
mpLabel.Text = "Welcome Fazio!";
}
You can create a public property in the masterpage that will change the label.
public string Heading
{
set
{
lblHeading.text = value;
}
}
It also depends on how deep your controls inside the Master page are. In my case, I had a Label control inside a ContentPlaceHolder control... so I had to do this...
Label myLBL = this.Master.FindControl("HeaderContent").FindControl("myLabel") as Label;

Categories