ASP.net get content page to change master page control - c#

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";
}
}

Related

ASP.NET Generic UserControl with Html Content Placeholder

This question might have already been asked, but I could not find any references to it so I apologize if it seems like a duplicate question.
What I'm trying to do is create a generic DialogBox as an ASP.NET UserControl; which would contain all the script required to create the dialog using jQuery. The dialog has a fixed set of buttons, but I'd like to be able to let the user define the content when they create the dialog. Suppose this is the markup for the user control:
<head>
<script type="text/javascript">
// jQuery script to create the dialog
</script>
</head>
<body>
<div runat="server" id="divContainer">
<!--Html Content Placeholder. What goes here?-->
</div>
</body>
And the code-behind:
[ParseChildren(true, "Contents")]
public partial class UCDialogBox : ExtendedUserControl
{
protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}
public List<Control> Contents { get; set; }
public DialogType Type { get; set; }
public string Title { get; set; }
}
And on the actual page after registering the control, I would like to be able to do something like this:
<uc:DialogBox runat="server">
<div>
<label>Hello World</label>
</div>
</uc:DialogBox>
The problem with this is, List<Control> only allows for ASP.NET controls. Normal HTML controls (such as what I have above) won't work.
Question 1: What type should I use to allow any HTML control to be nested inside the user control? I tried System.Web.UI.HtmlControls.HtmlControl but that didn't work either (ASP.NET says The element 'div' cannot be nested within the element 'dialogbox').
Question 2 What would I put as an HTML content placeholder on the user control which can be bound to the Contents property on the code behind? Something like
<SomePlaceholderControl DataSource="<%# Contents %>" />
Any help is appreciated.
Oddly enough, putting HTML controls inside the body of the user control doesn't cause a run-time error. In fact, the controls come across just fine. I guess it's just the designer that whines about it.
As for the placeholder, I didn't have to use any specific control; I simply used an HtmlTextWriter to render the controls into a well-formatted HTML string inside a method that gets called in the markup:
<div runat="server" id="divContainer">
<%# RenderContents() %>
</div>
And the code-behind method:
public string RenderContents()
{
StringWriter writer = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
foreach (var control in Contents)
{
control.RenderControl(htmlWriter);
}
return writer.ToString();
}
It works just fine.
I am not sure whether this is the correct approach, I have added a ITemplate inside the Dialog control and placed a HtmlGenericControl container which is Div control with runat = "server".
Now you can add the html controls and text inside this container.
<cc1:UCDialogBox ID="dialog" runat="server">
<HtmlPlaceHolder>
<div runat="server">
<h1>Title</h1>
<h2>Description</h2>
<div>Modal Content</div>
</div>
</HtmlPlaceHolder>
</cc1:UCDialogBox>
In custom server control you can get the container div content as innerHtml or innerText
public class UCDialogBox : WebControl, INamingContainer
{
private ITemplate htmlPlaceHolder = null;
[
Browsable(false),
DefaultValue(null),
Description("Add your html contorls"),
PersistenceMode(PersistenceMode.InnerProperty)
]
public virtual ITemplate HtmlPlaceHolder
{
get
{
return htmlPlaceHolder;
}
set
{
htmlPlaceHolder = value;
}
}
protected override void Render(HtmlTextWriter output)
{
HtmlGenericControl placeholder = new HtmlGenericControl();
htmlPlaceHolder.InstantiateIn(placeholder);
var html = placeholder.Controls[1] as System.Web.UI.HtmlControls.HtmlGenericControl;
var result = html.InnerHtml.Replace("\r", "").Replace("\n", "").Trim();
output.Write(result);
}
}

Not able to access master page control

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;
}

Accessing RadEditor control from master page's code behind...its not finding any radEditor control when it is there..whats wrong?

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?

How to select current menu in master pages?

In my web app (asp.net C#) I have menus as "All", "Education", "Fun", "Comedy". I want when I select All then it should be displayed as current menu, for which I have a CSS class current.
In case of WebUserControls I can do it easily by passing parameter of current page to select as below:
mywebpage.aspx
<uc:header ID="header1" runat="server" selectedMenu="comedy" />
header.ascx (code (c#))
public string selectedMenu
{
get { return strSelected; }
set { strSelected = value; }
}
header.ascx (html)
<ul>
<li><a href="/all/" title="All Videos" <%if (strSelected == "all"){%>class="current"<%} %>><span>All</span></a></li>
<li><a href="/fun/" title="Fun Videos" <%if (strSelected == "fun"){%>class="current"<%} %>><span>Fun</span></a></li>
<li><a href="/comedy/" title="Comedy Videos" <%if (strSelected == "comedy"){%>class="current"<%} %>><span>Comedy</span></a></li>
</ul>
When I'll pass comedy from my webpage to usercontrol then it will select comedy menu. I want to implement the same kind of functionality in case of master pages, could anyone tell me how to achieve this type of facility for master pages.
One way what I feel is to pass a query string parameter http://example.com/all/?select=all, I'll check on master page_load function if select parameter is "all" or fun or comedy then select corresponding menu. But this is not good, because I don't want to add an extra query string parameter to my URLs.
Please tell me how to solve this issue.
Thanks
You can access master page properties from your content page after casting the master to the correct type:
public class MyMasterPage : MasterPage
{
public string MyMenuProperty { get; set; }
protected void Page_PreRender(object sender, EventArgs e)
{
if (MyMenuProperty == "comedy")
{
/* do your menu stuff */
}
}
}
public class MyContentPage : Page
{
protected void Page_Load(object sender, EventArgs e)
{
var myMaster = Page.Master as MyMasterPage;
if (myMaster != null)
{
myMaster.MyMenuProperty = "comedy";
}
}
One way i have done simular in the past is add this to the page derivatives of any content pages:
<%# MasterType VirtualPath="~/YourMaster.master" %>
Then in the master i exposed this:
private PageTypes currentPageType;
public PageTypes CurrentPageType
{
get { return currentPageType; }
set { currentPageType = value; }
}
On this job this was used so the master knew what type of page it was on and therefore changed a few things, colours, controls etc. So from a contents pageload i did
Master.CurrentPageType = PageTypes.System;
One thing to note however, VS tends to moan about the MasterType derivative until you do a rebuild all.
I'm thinking that maybe a completely different approach might be easier to implement and maintain.
How about you just parse the URL in your header.ascx?
For example:
<li><a href="/all/" title="All Videos" runat="server" class='<%= Request.Url.ToString().Contains("/all/") ? "current" : "" %>' ><span>All</span></a></li>
That way, you won't have to worry about setting properties, accessing/casting master pages etc...
Hai prashant,
I had the same issue a month back and i posted in stack overflow check this one it may help you Find a UnorderedList <UL> control inside a master page from a content page in asp.net

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.

Categories

Resources