I have this in my Master page:
<asp:ContentPlaceHolder ID="BannerPlaceHolder" runat="server">
<asp:HyperLink ID="PortalBanner" runat="server"
ImageUrl="Images/banner-12-5-11.jpg"
NavigateUrl="~/Default.aspx"></asp:HyperLink>
</asp:ContentPlaceHolder>
I want to be able to change the hyperlink ImageUrl but I get a null exception:
Object reference not set to an instance of an object.
Here's my code to access the HyperLink
ContentPlaceHolder cp = (ContentPlaceHolder)this.Master.Master.FindControl("BannerPlaceHolder");
HyperLink hp= (HyperLink)cp.FindControl("PortalBanner");
Are you sure that it is in the Master of the Master? If not, simply change it to:
ContentPlaceHolder cp = (ContentPlaceHolder)this.Master.FindControl("BannerPlaceHolder");
Another approach is to provide a property in your master that you can access from your page by casting it to the actual type.
in the master's codebehind:
public string PortalBannerImageUrl
{
get {
return this.PortalBanner.ImageUrl;
}
set {
this.PortalBanner.ImageUrl = value;
}
}
in the page:
var myMaster = this.Master as YourMasterType;
if(myMaster != null)
{
myMaster.PortalBannerImageUrl = newImageUrl;
}
Related
I have been searching the internet and most I find resolves the issue of accessing the master page properties from the user control's code behind. But I am unable to find a solution where the user control can have access to the master page's properties within the markup.
Background:
The master page dynamically adds user control onto the page.
The master page has two properties which the user control needs to access via markup.
Here is some code to represent my problem:
Master page's code behind properties:
public IModule Module
{
get
{
return MyContext.Current.Module;
}
}
public IDictionary<string, object> Arguments
{
get
{
return MyContext.Current.Arguments;
}
}
Master page dynamically adds to control in code behind (it HAS to be dynamically added in master page's code behind):
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!(Page is VehicleForm) && !(Page is VsrManageForm) && !(Page is VpbManageForm))
{
MenuTab view = (MenuTab)this.LoadView(plhMenu, "~/Controls/MenuTab.ascx", "", MyContext.Current.Module);
}
}
User control's markup:
<web:FlowLink class="tools__lnk" arguments="<%# Arguments %>" id="flowLink1" runat="server" contextmodule='<%# Module %>' flowcall="FavouritesView" title="" rel="nofollow" ClientIDMode="Omitted">Shortlist</web:FlowLink>
<web:FlowLink class="tools__lnk" arguments="<%# Arguments %>" id="flowLink2" runat="server" contextmodule='<%# Module %>' flowcall="CompareView" title="" rel="nofollow" ClientIDMode="Omitted">Compare</web:FlowLink>
<web:FlowLink class="tools__lnk" arguments="<%# Arguments %>" id="flowLink5" runat="server" contextmodule='<%# Module %>' flowcall="UserView" title="" rel="nofollow" ClientIDMode="Omitted">Account</web:FlowLink>
Error:
Compiler Error Message: CS0103: The name 'Arguments' does not exist in the current context
Question:
How do I access <%# Arguments %> and <%# Module %> master page properties from the user control?
It might be possbile (have not tested it though) to do something like this:
arguments="<%# ((MasterPageType)this.Page.Master).Arguments %>"
Although it does not look right. You might want to redesign the way you control gets the data. Or atthe very least do the same somewhere in code behind and verify whether a current masterpage is of an expected type.
Update. The final solution that OP used incorporated ideas above, and resulted in having properties like below declared in the control:
public IDictionary<string, object> Arguments
{
get
{
MasterPageType master = this.Page.Master as MasterPageType;
if (master != null)
{
return master.Arguments;
}
else
{
return null;
}
}
}
I'm getting "Object reference not set to an instance of an object" exception, on the next line of code:
((HyperLink)Page.FindControl(id)).Visible = false;
What can be the problem?
Here is a sample from my code:
.aspx:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="FriendsList.aspx.cs" Inherits="Private_User_Social_FriendsList" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" Runat="Server">
</asp:Content>
<div class="FriendsProposal" runat="server">
<div class="FriendsProposal_Header">FriendsP</div>
<div id="FriendsProposalPH" class="FriendsProposalPH" runat="server"></div>
.aspx.cs:
public partial class Private_User_Social_FriendsList : System.Web.UI.Page
{
DBservices DBS = new DBservices();
protected void Page_Load(object sender, EventArgs e)
List<Friends> ListFriendsProposal = DBS.getFriendsProposal(User.Identity.Name.ToString());
foreach (Friends FRIndex in ListFriendsProposal)
{
string _FriendsOutput = FR_output(FRIndex);
HyperLink tempHL = new HyperLink();
tempHL.Text = _FriendsOutput;
tempHL.CssClass = "HyperLinkFriends";
tempHL.ID = FRIndex.UdName;
FriendsProposalPH.Controls.Add(new LiteralControl("<div style='height:32px' runat='server' >"));
FriendsProposalPH.Controls.Add(tempHL);
Button tempApprove = new Button();
tempApprove.Text = "Approve";
tempApprove.Click += new EventHandler(cmdUpdate_Click);
tempApprove.ID = FRIndex.UdName + "1";
FriendsProposalPH.Controls.Add(tempApprove);
FriendsProposalPH.Controls.Add(new LiteralControl("</div>"));
}
}
private void cmdUpdate_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string _tempID = btn.ID;
string id = _tempID.Substring(0, _tempID.LastIndexOf('1'));
DBS.ApproveFriend(User.Identity.Name.ToString(), id);
btn.Visible = false;
((HyperLink)Page.FindControl(id)).Visible = false;
}
Since you're adding the hyperlink to the FriendsProposalPH naming container (which is a placeholder control I presume) rather than the Page naming container, you should invoke the search method on that naming container and not the page itself (this method only searches within current naming container).
Judging by the code you provided the hyperlink is always added alongside the button, so perhaps the easiest way to access the right naming container and find and hide the hyperlink control is this:
btn.NamingContainer.FindControl(id).Visible = false;
your control that you are trying to find must have a runat="server" attribute or the exact same exception u receive is thrown.
dont forget that asp.net is request-response system, you cant access from the server a client-side controls.
if a control is not running at server, you cannot change it after client received it to his browser.
My master page contains this:
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
<asp:Label ID="User" runat="server" Text="Welcome, " Visible="false"></asp:Label>
</asp:ContentPlaceHolder>
I'm trying to access the label like this:
Label welcomeLabel;
ContentPlaceHolder cPlaceHolder;
cPlaceHolder = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");
if (cPlaceHolder != null)
{
welcomeLabel = (Label)cPlaceHolder.FindControl("User");
if (welcomeLabel != null)
{
welcomeLabel.Text = "Welcome, " + u.Name;
welcomeLabel.Visible = true;
}
}
I've checked that ContentPlaceHolder1 is actually found and using HasControls() on it returns true but I can't seem to access the label.
Help me?
I also having same prblem.
what i have done is
MasterPage ctl00 = FindControl("ctl00") as MasterPage;
ContentPlaceHolder cplacehld = ctl00.FindControl("ContentPlaceHolder1") as ContentPlaceHolder;
Label label1= cplacehld.FindControl("User") as Label;
try with:
((Label)this.Page.Master.FindControl("User")).Text = "Welcome, " + u.Name;
((Label)this.Page.Master.FindControl("User")).Visible = true;
This issue dogged me for about two hours until I realized that if I have a asp:Content tag on my page with the contentplaceholderID set to the ID for the contentplaceholder in the master page that I will never be able to access any controls in the contenplacholder. The asp:Content page is always merged with the MasterPage content, even if the asp:Content tag is empty on your content page. To provide for the default content, I moved my label outside of the contentplaceholder tag and set the visibility to false. If I then dynamically determined that I didn't have any content for my asp:Content tag I would then just set the label visibility to true to display my default content. Not exactly elegant, but it works.
Master page:
<form runat="server">
<Scirra:MainMenu runat="server" ID="MainMenu" TopTabSelected="home" SubTabSelected="link2" />
<asp:ContentPlaceHolder id="MainContent" runat="server">
snip
Content page:
Master.MainMenu.TopTabSelected = "forum";
I know I'm probably doing this wrong, but is this possible? I want to change a parameter of that control. It says 'inaccessible due to protection level'.
You should provide a public property f.e MenuTabSelected in your MasterPage that Gets/Sets this property of your Menu.
public string MenuTabSelected {
get { return MainMenu.TopTabSelected; }
set { MainMenu.TopTabSelected = value; }
}
Then you can access it in this way:
((YourMasterPage)Master).MenuTabSelected = "forum";
where YourMasterPage is the type of your MasterPage.
The compiler error is thrown because you want to access a private or protected control from outside of your MasterPage-Class. This would only be allowed if it would be public, what is not recommended. You have more control if you do it the way i suggested :)
find menu items in content page and change its value
protected void Page_Load(object sender, EventArgs e)
{
Menu mainMenu = (Menu)Page.Master.FindControl("NavigationMenu");
MenuItem menuMaterials = mainMenu.FindItem("Materials");
if (menuMaterials.Value == "Materials")
{
menuMaterials.Value = "NO materials";
menuMaterials.Text = "No materials";
}
}
Its not executing statements in if block in my method
Master Page:-
page load event:-
Control c = new Control();
DoSomething(c);
My method:-
protected void DoSomething(Control control)(
{
foreach (Control c in control.Controls)
{
if(typeof(c).Equals(Telerik.Web.UI.RadEditor))
{
Telerik.Web.UI.RadEditor rad = c as Telerik.Web.UI.RadEditor;
label1.Visible = true; label1.Text = "dhchk";
rad.CssFiles.Add("~/styles/myStyle.css");
rad.CssFiles.Add("~/styles/myStyle2.css");
rad.CssFiles.Add("~/styles/myStyle3.css");
}
else
{
DoSomething(c);
}
}
}
my content page:-
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<telerik:RadEditor ID="Editor1" EnableEmbeddedBaseStylesheet="false" EnableEmbeddedSkins=false runat="server">
</telerik:RadEditor>
<telerik:RadEditor ID="Editor2" EnableEmbeddedBaseStylesheet="false" EnableEmbeddedSkins=false runat="server">
</telerik:RadEditor>
[EDIT] ok when debugging..I rt clicked "c" and then Quick watch...it says "The name 'c' does not exist in the current context" (?!?!) how so ?
Well, the Master page renders first so you won't have access from the master page to any of the content page controls. You can achive this using events and passing the control from the content to the master
udpate:
Again - Accessing user controls from the master page is flaw in the whole master->content design. the closest thing I can imagine is adding static function
public static void AddDesign(RadEditor obj)
{
...
}
and then call the function form the Page_Load of the user control
MASTER_PAGE_CLASS_NAME.AddDesign(RadEditor1);
Well, I'm not sure, you can access controls in page like this.
At first: that editor should be probably in some Panel (or some other container), so i should look like this:
<asp:Panel ID="pnl1" runat="server">
<telerik:RadEditor ID="Editor1" EnableEmbeddedBaseStylesheet="false" EnableEmbeddedSkins=false runat="server" />
<telerik:RadEditor ID="Editor2" EnableEmbeddedBaseStylesheet="false" EnableEmbeddedSkins=false runat="server" />
</asp:Panel>
Then try this:
protected void Page_Load(object sender, EventArgs e)
{
foreach (Controls c in pnl1.Controls)
{
if (c is Telerik.Web.UI.RadEditor)
{
// do you stuff ...
}
}
}
You should change things around and call your MasterPage method from the content control.
In your masterpage add the method:
public void DoSomething(Telerik.Web.UI.RadEditor rad)
{
label1.Visible = true; label1.Text = "dhchk";
rad.CssFiles.Add("~/styles/myStyle.css");
rad.CssFiles.Add("~/styles/myStyle2.css");
rad.CssFiles.Add("~/styles/myStyle3.css");
}
Call the function from an appropriate event in your page/content control. eg Page.Load, Editor1.Load etc
Master.DoSomething(Editor1);
Update
From the masterpage, you should search for child controls in the Content controls
ContentPlaceHolder1.FindControl("Editor1");
or you could try something like:
foreach (Control c in ContentPlaceHolder1.Controls)
{
if(typeof(c).Equals(Telerik.Web.UI.RadEditor))
{
Telerik.Web.UI.RadEditor rad = c as Telerik.Web.UI.RadEditor;
label1.Visible = true; label1.Text = "dhchk";
rad.CssFiles.Add("~/styles/myStyle.css");
rad.CssFiles.Add("~/styles/myStyle2.css");
rad.CssFiles.Add("~/styles/myStyle3.css");
}
else
{
DoSomething(c);
}
}
The load and render events of the master page are fired after those of the content page (as said here). Hence the controls in the content page should be available by the time these two events are fired?