I made a fromshell. Its a class that inherits from CompositeControl. This is how I use my class:
<custom:FormShell ID="asdf" Header="My Form Shell" runat="server">
<custom:Item runat="server">
<p>This is the content of the form.</p>
<p>Can put any HTML or ASP controls here</p>
</custom:Item>
</custom:FormShell>
This is what it renders:
The problem is, I want to be able to use my window with this code:
<custom:FormShell ID="asdf" Header="My Form Shell" runat="server">
<p>This is the content of the form.</p>
<p>Can put any HTML or ASP controls here</p>
</custom:FormShell>
//e.i. This class does not use the Item class. //Content goes directly into the FormShell (as opposed to the example above that I am currently using)
My Question is, How can I get access to the item inner controls and html of my form in code behind, without putting it in a Item class first. Here is my FormShell.cs which hold the Item class and FormShell Class:
using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace myControls
{
//Item class that will hold the stuff to render in the formshell (this is what I want to get rid of)
public class Item : Control { }
[ParseChildren(true, "Items")]
public class FormShell : CompositeControl
{
protected const int SIDE_CELL_WIDTH = 30;
protected const string BACKGROUND_COLOR = "#d3d3d3";
protected const string HEADER_BACKGROUND_IMAGE = "url('http://www.marcrenaud.net/_static/_other/greypopup/MiddleUp.png')";
protected string[] CORNER_IMAGE = new string[4]
{
"http://www.marcrenaud.net/_static/_other/greypopup/CornerUpLeft.png",
"http://www.marcrenaud.net/_static/_other/greypopup/CornerUpRight2.png",
"http://www.marcrenaud.net/_static/_other/greypopup/CornerDownLeft.png",
"http://www.marcrenaud.net/_static/_other/greypopup/CornerDownRight.png"
};
//List of item classes (I want to get rid of this)
private ArrayList m_items = new ArrayList();
protected Table m_table = new Table();
protected TableRow[] m_row = new TableRow[3];
protected TableCell[,] m_cell = new TableCell[3, 3];
protected Label m_header = new Label();
/////////////////////////////// Look at this code /////////////////////////////////
protected void AddContent()
{
//I want to get rid of the Items class. Right now, i only figured out how to
//Put content into my Form Shell class via Item class.
//Is there something similar to this.controls.childrenDeclaredOnPresentationPage or something ?
m_cell[1, 1].Controls.Add((Control)m_items[0]);
}
[Browsable(false)]
public ArrayList Items
{
get { return m_items; }
}
//////////////////////////////////Look at this code end//////////////////////////////
protected override void CreateChildControls()
{
InitializeTable();
InitializeControlStructure();
InitializeTableStyles();
InitializeCorners();
InitializeCssStyles();
AddContent();
this.Controls.Add(m_table);
}
protected void InitializeTable()
{
//Init the rows and cells
for (int i = 0; i < 3; i++)
{
m_row[i] = new TableRow();
for (int j = 0; j < 3; j++)
{
m_cell[i, j] = new TableCell();
}
}
}
protected void InitializeControlStructure()
{
m_header.Text = Header;
m_cell[0, 1].Controls.Add(m_header);
m_table.Controls.Add(m_row[0]);
m_table.Controls.Add(m_row[1]);
m_table.Controls.Add(m_row[2]);
m_row[0].Controls.Add(m_cell[0, 0]);
m_row[0].Controls.Add(m_cell[0, 1]);
m_row[0].Controls.Add(m_cell[0, 2]);
m_row[1].Controls.Add(m_cell[1, 0]);
m_row[1].Controls.Add(m_cell[1, 1]);
m_row[1].Controls.Add(m_cell[1, 2]);
m_row[2].Controls.Add(m_cell[2, 0]);
m_row[2].Controls.Add(m_cell[2, 1]);
m_row[2].Controls.Add(m_cell[2, 2]);
}
protected void InitializeTableStyles()
{
m_table.CellPadding = 0;
m_table.CellSpacing = 0;
m_cell[0, 0].Width = SIDE_CELL_WIDTH;
m_cell[0, 2].Width = SIDE_CELL_WIDTH;
m_cell[1, 0].Width = SIDE_CELL_WIDTH;
m_cell[1, 2].Width = SIDE_CELL_WIDTH;
m_cell[2, 0].Width = SIDE_CELL_WIDTH;
m_cell[2, 2].Width = SIDE_CELL_WIDTH;
m_cell[1, 0].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR);
m_cell[1, 1].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR);
m_cell[1, 2].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR);
m_cell[2, 1].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR);
}
protected void InitializeCorners()
{
Image[] corner = new Image[4];
for (int i = 0; i < 4; i++)
{
corner[i] = new Image();
corner[i].GenerateEmptyAlternateText = true;
corner[i].ImageUrl = CORNER_IMAGE[i];
}
m_cell[0, 0].Controls.Add(corner[0]);
m_cell[0, 2].Controls.Add(corner[1]);
m_cell[2, 0].Controls.Add(corner[2]);
m_cell[2, 2].Controls.Add(corner[3]);
}
protected void InitializeCssStyles()
{
//Initialize the table
m_table.Style["font-family"] = "Arial";
//Initialize the header
m_cell[0, 1].Style["background-image"] = HEADER_BACKGROUND_IMAGE;
m_cell[0, 1].Style["color"] = "White";
m_cell[0, 1].Style["text-align"] = "center";
m_cell[0, 1].Style["font-weight"] = "bold";
m_cell[0, 1].Style["font-size"] = "16px";
//Initialize the content area
m_cell[1, 1].Style["font-size"] = "14px";
}
public string Header
{
get;
set;
}
}
}
1. The class Item : Control {} of yours does nothing.
2. The private ArrayList m_items also does nothing.
3. Controls within your <ShellForm></ShellForm> will be rendered within those tags too, so it gave you an illusion that you needed to add m_items[0,1] (whatever) at a m_row[1,2]... But that is not the case.
The Item class and everything with m_List can be removed, but then something "bad" occurs in at design time (asp/html markup), it leaves you with this:
<custom:FormShell runat="server" ID="id" />
A closed custom control tag, allowing no ASP nor HTML markup within it. Because it is closed!
Solution?
Create a public dummy property which will allow tags between start and end tag, but set its Browsable value to false and do not set its set; method:
[Browsable(false)] //Dummy to allow tags between <CustomServerContr> <AllowTags> </CustomServerContr>
public ArrayList Empty //The dummy/empty must be an arraylist
{
get { return new ArrayList(); }
}
There you go!
Now you can define your custom server control like this:
<ShellForm>
<asp:Button />
</ShellForm>
PS: This allows you to have multiple ASP and HTML markup between the custom control start and end tag. But if you are going to add custom child tags to the control yourself, like this:
Thanks for the quick reply. In the new code you created, i do not see where you specify that the content withing the FormShell tags needs to go into m_cell[1,1].
How do I specify that the content goes into that cell in the table?
If you really need it to go within "m_cell[1,1]", you would need to either delve into how the Panel control is created and then Inherit from Panel instead of CompositeControl, or you can take the easier route with Itemplate like this:
<custom:ShellForm>
<tablecell11>
<asp:Label />
<p>Some HTML </p>
</tablecell11>
</custom:ShellForm>
Then within the ShellForm class (control), specify the "tableCell11" tag:
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateControl)),
TemplateInstance(TemplateInstance.Single)]
public ITemplate tableCell11
{
get
{
return _privatetableCell11;
}
set
{
_privatetableCell11 = value;
}
}
The above "_privatetableCell11" is of course of a private variable of type ITemplate, because thats what the "function" returns/sets.
Then later when rendering/adding the controls:
_privateCell11.InstantiateIn(tablecell_m[1,0]);
Seriously: this "prettyprint", ehm... this wysiwyg is killing me! Like I want to "edit the html" to fix the "mistake"? No!
Marquis_DeBl...
Member
67 Points
51 Posts
How to get the inner text of a class that inherits from CompositeControl
Jul 04, 2011 08:48 PM|LINK
I made a fromshell. Its a class that inherits from CompositeControl. This is how I use my class:
<custom:FormShell ID="asdf" Header="My Form Shell" runat="server"> <custom:Item runat="server"> <p>This is the content of the form.</p> <p>Can put any HTML or ASP controls here</p> </custom:Item> </custom:FormShell>This is what it renders:
The problem is, I want to be able to use my window with this code:
<custom:FormShell ID="asdf" Header="My Form Shell" runat="server"> <p>This is the content of the form.</p> <p>Can put any HTML or ASP controls here</p> </custom:FormShell>
//e.i. This class does not use the Item class.
//Content goes directly into the FormShell (as opposed to the example above that I am currently using)
My Question is, How can I get access to the item inner controls and html of my form in code behind, without putting it in a Item class first. Here is my FormShell.cs which hold the Item class and FormShell Class:
using System; using System.Collections; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; namespace myControls { //Item class that will hold the stuff to render in the formshell (this is what I want to get rid of) public class Item : Control { } [ParseChildren(true, "Items")] public class FormShell : CompositeControl { protected const int SIDE_CELL_WIDTH = 30; protected const string BACKGROUND_COLOR = "#d3d3d3"; protected const string HEADER_BACKGROUND_IMAGE = "url('http://www.marcrenaud.net/_static/_other/greypopup/MiddleUp.png')"; protected string[] CORNER_IMAGE = new string[4] { "http://www.marcrenaud.net/_static/_other/greypopup/CornerUpLeft.png", "http://www.marcrenaud.net/_static/_other/greypopup/CornerUpRight2.png", "http://www.marcrenaud.net/_static/_other/greypopup/CornerDownLeft.png", "http://www.marcrenaud.net/_static/_other/greypopup/CornerDownRight.png" }; //List of item classes (I want to get rid of this) private ArrayList m_items = new ArrayList(); protected Table m_table = new Table(); protected TableRow[] m_row = new TableRow[3]; protected TableCell[,] m_cell = new TableCell[3, 3]; protected Label m_header = new Label(); /////////////////////////////// Look at this code ///////////////////////////////// protected void AddContent() { //I want to get rid of the Items class. Right now, i only figured out how to //Put content into my Form Shell class via Item class. //Is there something similar to this.controls.childrenDeclaredOnPresentationPage or something ? m_cell[1, 1].Controls.Add((Control)m_items[0]); } [Browsable(false)] public ArrayList Items { get { return m_items; } } //////////////////////////////////Look at this code end////////////////////////////// protected override void CreateChildControls() { InitializeTable(); InitializeControlStructure(); InitializeTableStyles(); InitializeCorners(); InitializeCssStyles(); AddContent(); this.Controls.Add(m_table); } protected void InitializeTable() { //Init the rows and cells for (int i = 0; i < 3; i++) { m_row[i] = new TableRow(); for (int j = 0; j < 3; j++) { m_cell[i, j] = new TableCell(); } } } protected void InitializeControlStructure() { m_header.Text = Header; m_cell[0, 1].Controls.Add(m_header); m_table.Controls.Add(m_row[0]); m_table.Controls.Add(m_row[1]); m_table.Controls.Add(m_row[2]); m_row[0].Controls.Add(m_cell[0, 0]); m_row[0].Controls.Add(m_cell[0, 1]); m_row[0].Controls.Add(m_cell[0, 2]); m_row[1].Controls.Add(m_cell[1, 0]); m_row[1].Controls.Add(m_cell[1, 1]); m_row[1].Controls.Add(m_cell[1, 2]); m_row[2].Controls.Add(m_cell[2, 0]); m_row[2].Controls.Add(m_cell[2, 1]); m_row[2].Controls.Add(m_cell[2, 2]); } protected void InitializeTableStyles() { m_table.CellPadding = 0; m_table.CellSpacing = 0; m_cell[0, 0].Width = SIDE_CELL_WIDTH; m_cell[0, 2].Width = SIDE_CELL_WIDTH; m_cell[1, 0].Width = SIDE_CELL_WIDTH; m_cell[1, 2].Width = SIDE_CELL_WIDTH; m_cell[2, 0].Width = SIDE_CELL_WIDTH; m_cell[2, 2].Width = SIDE_CELL_WIDTH; m_cell[1, 0].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); m_cell[1, 1].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); m_cell[1, 2].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); m_cell[2, 1].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); } protected void InitializeCorners() { Image[] corner = new Image[4]; for (int i = 0; i < 4; i++) { corner[i] = new Image(); corner[i].GenerateEmptyAlternateText = true; corner[i].ImageUrl = CORNER_IMAGE[i]; } m_cell[0, 0].Controls.Add(corner[0]); m_cell[0, 2].Controls.Add(corner[1]); m_cell[2, 0].Controls.Add(corner[2]); m_cell[2, 2].Controls.Add(corner[3]); } protected void InitializeCssStyles() { //Initialize the table m_table.Style["font-family"] = "Arial"; //Initialize the header m_cell[0, 1].Style["background-image"] = HEADER_BACKGROUND_IMAGE; m_cell[0, 1].Style["color"] = "White"; m_cell[0, 1].Style["text-align"] = "center"; m_cell[0, 1].Style["font-weight"] = "bold"; m_cell[0, 1].Style["font-size"] = "16px"; //Initialize the content area m_cell[1, 1].Style["font-size"] = "14px"; } public string Header { get; set; } } }Decker Dong ...
All-Star
118619 Points
18779 Posts
Re: How to get the inner text of a class that inherits from CompositeControl
Jul 06, 2011 02:29 AM|LINK
Hello:)
You can try this——
foreach(Control c in XXX.Controls)
{
//Do what you want....
}
colaoye
Member
61 Points
16 Posts
Re: How to get the inner text of a class that inherits from CompositeControl
Jul 07, 2011 04:23 AM|LINK
Hello!
1. The class Item : Control {} of yours does nothing.
2. The private ArrayList m_items also does nothing.
3. Controls within your <ShellForm></ShellForm> will be rendered within those tags too, so it gave you an illusion that you needed to add m_items[0,1] (whatever) at a m_row[1,2]... But that is not the case.
The Item class and everything with m_List can be removed, but then something "bad" occurs in at design time (asp/html markup), it leaves you with this:
A closed custom control tag, allowing no ASP nor HTML markup within it. Because it is closed!
Solution?
Create a public dummy property which will allow tags between start and end tag, but set its Browsable value to false and do not set its set; method:
[Browsable(false)] //Dummy to allow tags between <CustomServerContr> <AllowTags> </CustomServerContr> public ArrayList Empty //The dummy/empty must be an arraylist { get { return new ArrayList(); } }There you go!
Now you can define your custom server control like this:
PS: This allows you to have multiple ASP and HTML markup between the custom control start and end tag. But if you are going to add custom child tags to the control yourself, like this:
<custom:FormShell runat="server" ID="formsh"> <Header>Header Text</Header> <FooterImage>~/Images/footer.png</FooterImage> </custom:FormShell>The solution would be to create another child tag which allows ASP and HTML markup, how? Through Itemplate class as a public property.
Full code:
[ParseChildren(true, "Empty")] public class FormShell : CompositeControl { protected const int SIDE_CELL_WIDTH = 30; protected const string BACKGROUND_COLOR = "#d3d3d3"; protected const string HEADER_BACKGROUND_IMAGE = "url('http://www.marcrenaud.net/_static/_other/greypopup/MiddleUp.png')"; protected string[] CORNER_IMAGE = new string[4] { "http://www.marcrenaud.net/_static/_other/greypopup/CornerUpLeft.png", "http://www.marcrenaud.net/_static/_other/greypopup/CornerUpRight2.png", "http://www.marcrenaud.net/_static/_other/greypopup/CornerDownLeft.png", "http://www.marcrenaud.net/_static/_other/greypopup/CornerDownRight.png" }; protected Table m_table = new Table(); protected TableRow[] m_row = new TableRow[3]; protected TableCell[,] m_cell = new TableCell[3, 3]; protected Label m_header = new Label(); [Browsable(false)] //Dummy to allow tags between <FormShell> <allows Tags Here> </FormShell> public ArrayList Empty //The dummy/empty must be an arraylist (not tested EVERY class, but...) { get { return new ArrayList(); } } protected override void CreateChildControls() { InitializeTable(); InitializeControlStructure(); InitializeTableStyles(); InitializeCorners(); InitializeCssStyles(); this.Controls.Add(m_table); } protected void InitializeTable() { //Init the rows and cells for (int i = 0; i < 3; i++) { m_row[i] = new TableRow(); for (int j = 0; j < 3; j++) { m_cell[i, j] = new TableCell(); } } } protected void InitializeControlStructure() { m_header.Text = Header; m_cell[0, 1].Controls.Add(m_header); m_table.Controls.Add(m_row[0]); m_table.Controls.Add(m_row[1]); m_table.Controls.Add(m_row[2]); m_row[0].Controls.Add(m_cell[0, 0]); m_row[0].Controls.Add(m_cell[0, 1]); m_row[0].Controls.Add(m_cell[0, 2]); m_row[1].Controls.Add(m_cell[1, 0]); m_row[1].Controls.Add(m_cell[1, 1]); m_row[1].Controls.Add(m_cell[1, 2]); m_row[2].Controls.Add(m_cell[2, 0]); m_row[2].Controls.Add(m_cell[2, 1]); m_row[2].Controls.Add(m_cell[2, 2]); } protected void InitializeTableStyles() { m_table.CellPadding = 0; m_table.CellSpacing = 0; m_cell[0, 0].Width = SIDE_CELL_WIDTH; m_cell[0, 2].Width = SIDE_CELL_WIDTH; m_cell[1, 0].Width = SIDE_CELL_WIDTH; m_cell[1, 2].Width = SIDE_CELL_WIDTH; m_cell[2, 0].Width = SIDE_CELL_WIDTH; m_cell[2, 2].Width = SIDE_CELL_WIDTH; m_cell[1, 0].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); m_cell[1, 1].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); m_cell[1, 2].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); m_cell[2, 1].BackColor = System.Drawing.ColorTranslator.FromHtml(BACKGROUND_COLOR); } protected void InitializeCorners() { Image[] corner = new Image[4]; for (int i = 0; i < 4; i++) { corner[i] = new Image(); corner[i].GenerateEmptyAlternateText = true; corner[i].ImageUrl = CORNER_IMAGE[i]; } m_cell[0, 0].Controls.Add(corner[0]); m_cell[0, 2].Controls.Add(corner[1]); m_cell[2, 0].Controls.Add(corner[2]); m_cell[2, 2].Controls.Add(corner[3]); } protected void InitializeCssStyles() { //Initialize the table m_table.Style["font-family"] = "Arial"; //Initialize the header m_cell[0, 1].Style["background-image"] = HEADER_BACKGROUND_IMAGE; m_cell[0, 1].Style["color"] = "White"; m_cell[0, 1].Style["text-align"] = "center"; m_cell[0, 1].Style["font-weight"] = "bold"; m_cell[0, 1].Style["font-size"] = "16px"; //Initialize the content area m_cell[1, 1].Style["font-size"] = "14px"; } public string Header { get; set; }Marquis_DeBl...
Member
67 Points
51 Posts
Re: How to get the inner text of a class that inherits from CompositeControl
Jul 08, 2011 03:32 PM|LINK
Hi colaoye.
Thanks for the quick reply. In the new code you created, i do not see where you specify that the content withing the FormShell tags needs to go into m_cell[1,1].
How do I specify that the content goes into that cell in the table?
Before I used the code
Marc
colaoye
Member
61 Points
16 Posts
Re: How to get the inner text of a class that inherits from CompositeControl
Jul 10, 2011 06:41 PM|LINK
If you really need it to go within "m_cell[1,1]", you would need to either delve into how the Panel control is created and then Inherit from Panel instead of CompositeControl, or you can take the easier route with Itemplate like this:
Then within the ShellForm class (control), specify the "tableCell11" tag:
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl)), TemplateInstance(TemplateInstance.Single)] public ITemplate tableCell11 { get { return _privatetableCell11; } set { _privatetableCell11 = value; }The above "_privatetableCell11" is of course of a private variable of type ITemplate, because thats what the "function" returns/sets.
Then later when rendering/adding the controls:
Seriously: this "prettyprint", ehm... this wysiwyg is killing me! Like I want to "edit the html" to fix the "mistake"? No!
Marquis_DeBl...
Member
67 Points
51 Posts
Re: How to get the inner text of a class that inherits from CompositeControl
Jul 11, 2011 05:37 PM|LINK
Hi Colaoye.
Thanks for the feedback.
Any Idea on how to user my for inheriting from Panel control? Where is the inner content stored? How would you build my FormShell in code?