I need to write a user control that can be used with the following syntax:
<quiz:Question runat="server">
<Answer>Foo</Answer>
<Answer>Bar</Answer>
</quiz:Question>
I tried the following property declaration:
[ParseChildren(true, "Answer")]
public class Question : UserControl
{
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public string[] Answer { get; set; }
}
But then the Visual Studio editor insist that <Answers >
should be self-closing and I get this exception if I decide otherwise:
Literal content ('Foo') is not allowed within a 'System.String[]'.
I have been looking at <asp:DropDownList>
in Reflector, which inherits from ListControl
which declares the Items
property as follows:
ParseChildren(true, "Items")
public abstract class ListControl
{
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public virtual ListItemCollection Items { get; }
}
It's not really the same as what I want, because in DropDownList
you must add <asp:ListItem>
as children. And there are some things I don't understand about control design, which is currently preventing me from finding the solution:
<asp:ListItem>
tag require a runat="server"
attribute?User Control properties are used to set the values of a User Control from the parent page.
IsPostBack is a property of the Asp.Net page that tells whether or not the page is on its initial load or if a user has perform a button on your web page that has caused the page to post back to itself. The value of the Page.
The runat attribute basically tells ASP.Net that it needs to parse the element, its attributes and it's contents as a server control. Enabling code, on the server, to be executed to configure the response. Without it, any child controls contained within the <head> section will not get parsed.
ASP.NET has five list-type controls: BulletedList, ListBox, DropDownList, CheckBoxList, and RadioButtonList. These four controls inherits from the same base class, called ListControl.
I mixed behavior of controls those can have child items (like ListControl), with controls like Panel (ParseChildren=false) :
[ParseChildren(true, "Answers")]
public class Question : WebControl, INamingContainer
{
private AnswerCollection answers;
public virtual AnswerCollection Answers
{
get
{
if (this.answers == null)
{
this.answers = new AnswerCollection();
}
return this.answers;
}
}
public override void RenderControl(HtmlTextWriter writer)
{
//access to each answer value
foreach (var a in this.Answers)
writer.WriteLine(((LiteralControl)a.Controls[0]).Text + "<br/>");
}
}
[ParseChildren(false), PersistChildren(true)]
public class Answer : Control
{
}
public class AnswerCollection : List<Answer>
{
}
Then you would be able to have something like :
<cc1:Question runat="server">
<cc1:Answer>Answer1</cc1:Answer>
<cc1:Answer>Answer2</cc1:Answer>
</cc1:Question>
Hope it helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With