Custom Control Properties not initializing properly
The First - LblTextBox: A label and textbox that have a LabelText field that can be set to change the label text
The Second - LoginCtl: A login control that has two instances of LblTextBox for user name, password and a submit button
I want to control the tag rendering of these controls for formatting so I am not overriding CreateChildControls() to get the job done.
My issue is that the controls are rendered but none of the OnInit() code in either controls takes hold (blank labels, css styles not applied, etc..).
Any direction would be great!
public class LblTextBox : CompositeControl
{
public string LabelText { get; set; }
public string Text { get; set; }
TextBox input;
Label label;
RequiredFieldValidator evalReqField;
public LblTextBox()
{
label = new Label();
input = new TextBox();
evalReqField = new RequiredFieldValidator();
}
protected override void OnInit(EventArgs e)
{
label.ID = "lblTextBox";
label.Text = string.Format("{0}:", LabelText);
input.ID = "tbInput";
evalReqField.ID = "evalInput";
evalReqField.ControlToValidate = input.ID;
evalReqField.ErrorMessage = "(Required)";
evalReqField.Display = ValidatorDisplay.Dynamic;
}
protected override void RenderChildren(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Div);
label.RenderControl(writer);
input.RenderControl(writer);
evalReqField.RenderControl(writer);
writer.RenderEndTag();
}
}
public class LoginCtl : CompositeControl
{
public string UserName
{
get
{
return (ltbUser != null) ? ltbUser.Text : string.Empty;
}
set
{
if (ltbUser != null)
ltbUser.Text = value;
}
}
public string Password
{
get
{
return (ltbPass != null) ? ltbPass.Text :开发者_如何学运维 string.Empty;
}
set
{
if (ltbPass != null)
ltbPass.Text = value;
}
}
private LblTextBox ltbUser;
private LblTextBox ltbPass;
private Button btnSubmit;
public LoginCtl()
{
ltbUser = new LblTextBox();
ltbPass = new LblTextBox();
btnSubmit = new Button();
}
protected override void OnInit(EventArgs e)
{
ltbUser.LabelText = "User Name";
ltbPass.LabelText = "Password";
btnSubmit.Text = "Submit";
btnSubmit.CssClass = "Submit";
}
protected override void RenderChildren(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "LoginCtlDiv");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
ltbUser.RenderControl(writer);
ltbPass.RenderControl(writer);
btnSubmit.RenderControl(writer);
writer.RenderEndTag();
}
}
The goal was to be able to set properties in the aspx Markup using the control. However, the properties were never initialized.
My error was in the understanding of using CreateChildControls() and RenderChildren(..) I thought that it was to use one or the other. Instead, I instantiate all the child controls and add them in CreateChildControls().
In order to load the properties, I wait till the OnPreRender() event. The controls will all be loaded and so will the data. Then I make the final changes before the control is rendered to the page.
Another little note, I really wanted to change the default tag that is wrapped around my controls for display purposes (ASP will wrap it with a span by default). So if you want a block level elem this will cause a problem. If you override the TagKey property and set it to an enum elem it will use that instead of the default span tag.
I restructured it as the following:
public class LblTextBox : CompositeControl
{
protected override void OnPreRender(EventArgs e)
{
label.Text = string.Format("{0}:", LabelText);
base.OnPreRender(e);
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
protected override void CreateChildControls()
{
label = new Label();
input = new TextBox();
evalReqField = new RequiredFieldValidator();
label.ID = "lblTextBox";
input.ID = "tbInput";
evalReqField.ID = "evalInput";
evalReqField.ControlToValidate = input.ID;
evalReqField.ErrorMessage = "(Required)";
evalReqField.Display = ValidatorDisplay.Dynamic;
Controls.Add(label);
Controls.Add(input);
Controls.Add(evalReqField);
base.CreateChildControls();
}
public string LabelText { get; set; } //label text
public string Text { get; set; } //text in textbox
TextBox input;
Label label;
RequiredFieldValidator evalReqField;
}
public class LoginCtl : CompositeControl
{
protected override void CreateChildControls()
{
ltbUser = new LblTextBox();
ltbPass = new LblTextBox();
btnSubmit = new Button();
ltbUser.LabelText = "User Name";
ltbPass.LabelText = "Password";
ltbPass.MargBetween = "10px";
btnSubmit.Text = "Submit";
btnSubmit.CssClass = "Submit";
Controls.Add(ltbUser);
Controls.Add(ltbPass);
Controls.Add(btnSubmit);
}
//..
//..
private LblTextBox ltbUser;
private LblTextBox ltbPass;
private Button btnSubmit;
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Div;
}
}
}
I don't remember why (I'll try to recall), but I had very similar problem few months ago, and my solution was to initialize all of properties except of "ID" in OnLoad event handler:
protected override void OnLoad(EventArgs e)
{
label.Text = string.Format("{0}:", LabelText);
evalReqField.ControlToValidate = input.ID;
evalReqField.ErrorMessage = "(Required)";
evalReqField.Display = ValidatorDisplay.Dynamic;
}
Hope this helps
精彩评论