ASP.NET Content Web Form - content from placeholder disappears - asp.net

I'm attempting to set a class on the body tag in my asp.net site which uses a master page and content web forms. I simply want to be able to do this by adding a bodycssclass property (see below) to the content web form page directive.
It works through the solution below but when i attempt to view Default.aspx the Content1 control loses its content. Any ideas why?
Here is how I'm doing it. I have a master page with the following content:
<%# Master Language="C#" ... %>
<html><head>...</head>
<body id=ctlBody runat=server>
<asp:ContentPlaceHolder ID="cphMain" runat="server" />
</body>
</html>
it's code behind looks like:
public partial class Site : MasterPageBase
{
public override string BodyCssClass
{
get { return ctlBody.Attributes["class"]; }
set { ctlBody.Attributes["class"] = value; }
}
}
it inherits from:
public abstract class MasterPageBase : MasterPage
{
public abstract string BodyCssClass
{
get;
set;
}
}
my default.aspx is defined as:
<%# Page Title="..." [master page definition etc..] bodycssclass="home" %>
<asp:Content ID="Content1" ContentPlaceHolderID="cphMain" runat="server">
Some content
</asp:Content>
the code behind for this file looks like:
public partial class Default : PageBase { ... }
and it inherits from :
public class PageBase : Page
{
public string BodyCssClass
{
get
{
MasterPageBase mpbCurrent = this.Master as MasterPageBase;
return mpbCurrent.BodyCssClass;
}
set
{
MasterPageBase mpbCurrent = this.Master as MasterPageBase;
mpbCurrent.BodyCssClass = value;
}
}
}

This works for me now...
public class PageBase : Page
{
public string BodyCssClass
{
get;
set;
}
protected override void OnPreInit(EventArgs e)
{
MasterPageBase mpbCurrent = this.Master as MasterPageBase;
mpbCurrent.BodyCssClass = BodyCssClass;
base.OnLoadComplete(e);
}
}

Have you tried adding the MasterType directive to your content page? Like so:
I recommend doing that anyway. Let's see if that helps you...
See http://msdn.microsoft.com/en-us/library/ms228274.aspx
and http://msdn.microsoft.com/en-us/library/c8y19k6h.aspx

Related

User control with collection property: object is of type 'System.Web.UI.HtmlControls.HtmlGenericControl'

I'm creating a user control that has a collection property. I've done a lot of research and I think it's, for the most part, correct. The probem is when I define the collection via markup, I get an error:
UserControls.BreadcrumbItemCollection
must have items of type UserControls.BreadcrumbItem'.'BreadcrumbItem' is of
type 'System.Web.UI.HtmlControls.HtmlGenericControl'.
I'm unsure why the TemplateParser thinks that BreadCrumbItem is of type 'System.Web.UI.HtmlControl.HtmlGenericControl', but what can I do in the user control to remedy this? If I make a property that is of type BreadCrumbItem (no collection) the TemplateParser works parses the markup an generates a BreadcrumbItem instance just fine, so why not on a collection?
Here is my user control:
[PersistChildren(false)]
public partial class Breadcrumb : System.Web.UI.UserControl, INamingContainer
{
private readonly BreadcrumbItemCollection lstBreadCrumbs_m = new BreadcrumbItemCollection();
[PersistenceMode(PersistenceMode.InnerProperty)]
public BreadcrumbItemCollection Items { get; set; }
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public class BreadcrumbItemCollection : System.Collections.Generic.List<BreadcrumbItem>
{
}
[Serializable]
public class BreadcrumbItem
{
public BreadcrumbItem()
{
}
public BreadcrumbItem(string sValue)
: base()
{
this.Value = sValue;
}
public string Value
{
get;
set;
}
public override string ToString()
{
return this.Value;
}
/// <summary>
/// explicit string to BreadcrumbItem operator
/// </summary>
/// <param name="sValue"></param>
/// <returns></returns>
public static explicit operator BreadcrumbItem(string sValue)
{
BreadcrumbItem crumb = new BreadcrumbItem(sValue); // explicit conversion
return crumb;
}
}
My markup looks as follows:
<%# Page ...
<%# Register Src="~/UserControls/Breadcrumb.ascx" TagPrefix="uc1" TagName="Breadcrumb" %>
...
<uc1:Breadcrumb runat="server" ID="Breadcrumb">
<Items>
<BreadcrumbItem Value="test"></BreadcrumbItem>
</Items>
</uc1:Breadcrumb>
You should look at this:
http://msdn.microsoft.com/en-us/library/sbz9etab(v=vs.90).aspx
Especially this tag at the top of the page
<%# Register TagPrefix="uc" TagName="Spinner" Src="~/Controls/Spinner.ascx" %>
The fact that you're trying to inherit from System.Web.UI.UserControl could be causing an issue. Try inheriting from System.Web.UI.WebControl instead.

Call Public Property Declared in a ASPX Page from a Different ASPX Page

How can I call a public property declared on a ASPX page from a different ASPX Page? Is that possible? It is a website project. How can I get/call this property from a different aspx page? I have attempted this from the other page, but it is not recognizing the partial class: private Test_Default _test; It does not recognize the "Test_Default"
I.E.
public partial class Test_Default : System.Web.UI.Page
{
private string myAge = string.empty;
public string Name
{
get
{
return myName;
}
set
{
myName = value;
}
}
If you need a piece of shared code, create a class for it in the APP_CODE folder.
See MSDN documentation here and here.
I would create a separate class exposing the property you are wanting to work with, and store the value in Session :
public class MyClass
{
public static string MyName
{
get
{
if (Session["MY_NAME"] != null)
{
return Session["MY_NAME"].ToString();
}
return String.Empty;
}
set { Session["MY_NAME"] = value; }
}
}
You should be able to call that from either Page. If it's a complex object, then change the type from string to your object.
Hope that helps!!

ASP.NET ITemplate with TemplateInstance.Multiple

I can't seem to find any examples on how to implement ITemplates with multiple instances. All I need to do is build out a navigation that has a template for the content of each navigation item.
If your control is not a databound control, you can solve the problem by something as follows. But, I haven't tested it.
public class FooItem : WebControl, INamingContainer
{
protected override CreateChildControls()
{
Control placeHolder = this.FindControl(((Foo)this.Parent).ItemPlaceHolderId);
if (placeHolder != null)
{
// Add some controls to the placeHolder.
}
}
}
public class Foo : WebControl, INamingContainer
{
public ITemplate ItemTemplate { get; set; }
public string ItemPlaceHolderId
{
get { ... }
set { ... }
}
public FooItemCollection Items
{
get { ... }
}
protected override CreateChildControls()
{
foreach (FooItem item in this.Items)
{
this.ItemTemplate.InstantiateIn(item);
}
}
}
Look at documentation of creating a data-bound templated control.
Unfortunately, the best documentation I've found is from .NET 1.1:
Developing a Templated Data-Bound Control.
Note from MSDN:
This TemplateInstanceAttribute class
is optional. If a template property is
not extended with a
TemplateInstanceAttribute class, the
default value, the Multiple field, is
used.
So any ITemplate example that does not use the TemplateInstanceAttribute is using TemplateInstance.Multiple.

ASP.NET Templated Control

I'm attempting to build a templated control. You'll see that as part of the Field section, I'd like to be able to define controls as children. When I attempt to compile I'm receiving the error message "MyTemplateControl.Field' does not have a public property named 'Button'". Does anyone know how to accomplish what I'm trying to do?
Below you'll find an example XHTML markup, and below that my control implementation.
I've editted my example to hopefully clarify what I'm looking for. Thanks everyone for the MSDN links. I've been through those already.
What I'm trying to build is a data entry control that will auto format a table for me. We do a lot of data entry webforms, and I'd like to ease the implementation time.
<cc1:MyForm ID="MyForm1" runat="server">
<ViewTemplate>
<cc1:Field Question="What is your name?">
<asp:Label ID="myLabel" runat="server" />
</cc1:Field>
</ViewTemplate>
<EditTemplate>
<cc1:Field Question="What is your name?">
<asp:Textbox ID="myTextbox" runat="server" />
</cc1:Field>
</EditTemplate>
</cc1:MyForm>
public class MyForm : WebControl, INamingContainer
{
private FieldCollection _fieldCollection;
private FieldCollection _field2Collection;
public FieldCollection ViewTemplate
{
get
{
if (_fieldCollection == null)
{
_fieldCollection = new FieldCollection();
}
return _fieldCollection;
}
}
public FieldCollection EditTemplate
{
get
{
if (_field2Collection == null)
{
_field2Collection = new FieldCollection();
}
return _field2Collection;
}
}
}
public class FieldCollection : CollectionBase
{
.
.
.
}
[ParseChildren(false)]
public class Field
{
.
.
.
}
There's something strange in your implementation. It's difficult to understand what you'd like to do, either to build a templated control, or a control on which you can add a list of child controls.
For the templated approach you'd have to do something like this:
public class MyForm : WebControl, INamingContainer
{
private TemplateOwner templateOwner{ get; set; }
private ITemplate _Content;
public ITemplate Content
{
get
{
return this._Content;
}
set
{
_Content = value;
}
}
protected override void CreateChildControls()
{
base.Controls.Clear();
templateOwner = new TemplateOwner();
this.Content.InstantiateIn(templateOwner);
this.Controls.Add(templateOwner);
}
...
}
[ToolboxItem(false)]
public class TemplateOwner : WebControl{
public TemplateOwner():base(HtmlTextWriterTag.Div)
{
}
}
The usage would then look like
<cc1:MyForm ID="MyForm1" runat="server">
<Content>
<!-- Place whatever HTML, ASP.net controls etc you like -->
</Content>
</cc1:MyForm>
You still have to add the appropriate annotations to configure the behavior of the designer. I just wrote this down quickly to give you an idea.
GridView also doesn't allow such manipulation,
Instead use MyForm1.FindControl("mybutton")
Also I have notice your template is not derived from ITemplate interface. As usual ASP.Net also uses System.Web.UI.Control as base class for this impl.
I used the following code:
public partial class SmallFramedControl : UserControl, INamingContainer
{
private TemplateOwner templateOwner { get; set; }
private ITemplate _Content;
public ITemplate Content
{
get
{
return this._Content;
}
set
{
_Content = value;
}
}
protected override void CreateChildControls()
{
//base.Controls.Clear();
templateOwner = new TemplateOwner();
this.Content.InstantiateIn(templateOwner);
plchAdd.Controls.Add(templateOwner);
}
protected void Page_Load(object sender, EventArgs e)
{
}
}
[ToolboxItem(false)]
public class TemplateOwner : WebControl
{
public TemplateOwner()
: base(HtmlTextWriterTag.Div)
{
}
}
and ascx page look like:
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="SmallFramedControl.ascx.cs"
Inherits="OtPortalNewDesign.UserControls.SmallFramedControl" %>
this will be top of frame
<asp:PlaceHolder ID="plchAdd" runat="server"></asp:PlaceHolder>
this will be bottom of frame

Set Property Value on Master Page from Content Page

I need to pass data to a variable in my master page each time a page is loaded.
I have a string[] of RequiredRoles that I set on each content page defining what roles are required to access that page.
On my master page, I have a method that takes this array, and checks to see if the current user is in one or more of those roles.
How would I go about managing this? I basically want each page to have a String[] RequiredRoles defined, and the master page will load this on each call and check to see if the users are in those roles.
Add page directive to your child page:
<%# MasterType VirtualPath="~/MasterPage.master" %>
Then add property to your master page:
public string Section { get; set; }
You can access this property like this:
Master.Section = "blog";
Typecast Page.Master to your master page so that you are doing something like:
((MyMasterPageType)Page.Master).Roles = "blah blah";
Create a property in your master page and you access it from content page:
Master page:
public partial class BasePage : System.Web.UI.MasterPage
{
private string[] _RequiredRoles = null;
public string[] RequiredRoles
{
get { return _RequiredRoles; }
set { _RequiredRoles = value; }
}
}
Content Page:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load()
{
Master.RequiredRoles = new string[] { /*set appropriate roles*/ };
}
}
I'd go by creating a base class for all the content pages, something like:
public abstract class BasePage : Page
{
protected abstract string[] RequiredRoles { get; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// display the required roles in a master page
if (this.Master != null) {
// value-assignment
}
}
}
And then I make every page inherits from BasePage, and each defining a RequiredRoles
public partial class _Default : BasePage
{
protected override string[] RequiredRoles
{
get { return new[] { "Admin", "Moderator" }; }
}
}
This has the advantage of cleanliness and DRY-ing the OnLoad handler code. And every page which inherits from BasePage are required to define a "RequiredRoles" or else it won't compile.
CType(Master.FindControl("lblName"), Label).Text = txtId.Text
CType(Master.FindControl("pnlLoginned"), Panel).Visible = True

Resources