如何验证复合控件
Posted
技术标签:
【中文标题】如何验证复合控件【英文标题】:how to validate composite controls 【发布时间】:2012-12-02 17:03:15 【问题描述】:好吧,这有点复杂。
我有一个包含文本框、必填字段验证器和一个按钮的复合控件。 它公开了一个名为 ValidationGroup 的属性。
它将 ValidationGroup 属性应用于文本框、必填字段验证器和按钮。
一切正常。
当我取出按钮并将其放在具有相同验证组的表单中时,问题就开始了。
理想情况下它应该有效。但事实并非如此。 有人说复合控件有自己的命名容器,所以这是行不通的。
如果这是真的,我不明白为什么?我的意思是他们有相同的验证组!
无论如何,有人知道如何解决这个问题吗?
这是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using FCC.Web.UI.CustomControl;
using System.Xml;
namespace FCC.Web.UI.CustomControl
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[DefaultProperty("Value")]
[ValidationProperty("Value")]
[ToolboxData("<0:ValidationTextBox runat=server></0:ValidationTextBox>")]
public class ValidationTextBox : CompositeControl, IDynamicControl
#region-- privatess --
private TextBox textBox1;
private RequiredFieldValidator requiredFieldValidator1;
private RegularExpressionValidator regularExpressionValidator1, maxlengthValidator,integerValidator,decimalValidator;
private string validationClasses, validationGroup, validationExpression, xmlElementName;
private bool isRequired;
private int maxlength;
#endregion
#region-- properties -- The following properties are deleted to child controls
#region-- textbox --
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
[Description("Text displayed on the textbox")]
public string Value
get
EnsureChildControls();
return textBox1.Text;
set
EnsureChildControls();
textBox1.Text = value;
[Bindable(true)]
[Category("Styles")]
[Themeable(true)]
[DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Localizable(true)]
public Style TextBoxStyle
get
EnsureChildControls();
return textBox1.ControlStyle;
set
EnsureChildControls();
//textBox1.Attributes["style"] = value;
textBox1.ControlStyle.MergeWith(value);
[Bindable(true)]
[Category("Styles")]
[Localizable(true)]
public string TextBoxCssClass
get
EnsureChildControls();
return textBox1.CssClass;
set
EnsureChildControls();
textBox1.CssClass = value;
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public TextBoxMode TextMode
get
EnsureChildControls();
return textBox1.TextMode;
set
EnsureChildControls();
textBox1.TextMode = value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
public int MaxLength
get
EnsureChildControls();
return maxlength;
set
EnsureChildControls();
if (value > 0)
maxlength = value;
textBox1.MaxLength = value;
maxlengthValidator.Enabled = true;
//maxlengthValidator.ValidationExpression = "^[a-zA-Z.]0," + value + "$";
maxlengthValidator.ValidationExpression = @"^[\s\S]0," + value + "$";
maxlengthValidator.ErrorMessage = "Maximum allowed charaters: " + value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
public bool IsInteger
get
EnsureChildControls();
return integerValidator.Enabled;
set
EnsureChildControls();
if (value == true) // Is Integer
integerValidator.Enabled = true;
regularExpressionValidator1.Enabled = false;
maxlengthValidator.Enabled = false;
decimalValidator.Enabled = false;
else
integerValidator.Enabled = false;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
[Description("Error message that appears when textbox contain invalid integer")]
public string InvalidIntegerErrorMessage
get
EnsureChildControls();
return integerValidator.ErrorMessage.IsNullOrEmpty() ? "Invalid Number" : integerValidator.ErrorMessage;
set
EnsureChildControls();
integerValidator.ErrorMessage = value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
public bool IsDecimal
get
EnsureChildControls();
return decimalValidator.Enabled;
set
EnsureChildControls();
if (value == true)
decimalValidator.Enabled = true;
integerValidator.Enabled = false;
regularExpressionValidator1.Enabled = false;
maxlengthValidator.Enabled = false;
else
decimalValidator.Enabled = false;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
[Description("Error message that appears when textbox contain invalid decimal number")]
public string InvalidDecimalErrorMessage
get
EnsureChildControls();
return decimalValidator.ErrorMessage.IsNullOrEmpty() ? "Invalid Number" : decimalValidator.ErrorMessage;
set
EnsureChildControls();
decimalValidator.ErrorMessage = value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
[Description("Name of XmlElement")]
public string XmlElementName
get
EnsureChildControls();
return xmlElementName;
set
EnsureChildControls();
xmlElementName = value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
public string XmlElements
get
EnsureChildControls();
return string.Format("<0>1</0>",XmlElementName,textBox1.Text);
#endregion
#region--required validation --
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
[Description("Error message that appears when text box is empty")]
public String RequiredErrorMessage
get
EnsureChildControls();
return requiredFieldValidator1.ErrorMessage.IsNullOrEmpty() ? "Required Field" : requiredFieldValidator1.ErrorMessage;
set
EnsureChildControls();
requiredFieldValidator1.ErrorMessage = value;
[Bindable(true)]
[Category("Default")]
[Localizable(true)]
[Description("bool, representing text in the textbox is required field or not")]
public bool IsRequired
get
EnsureChildControls();
return isRequired;
set
EnsureChildControls();
isRequired = value;
requiredFieldValidator1.Enabled = value;
#endregion
#region-- regular expression validation --
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
[Description("Error message that appears when textbox contain invalid format string")]
public String RegularExpressionErrorMessage
get
EnsureChildControls();
return regularExpressionValidator1.ErrorMessage.IsNullOrEmpty() ? "Invalid Text" : regularExpressionValidator1.ErrorMessage;
set
EnsureChildControls();
regularExpressionValidator1.ErrorMessage = value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
[Description("Regular expression. Leave blank if you dont want to implement.")]
public string RegularExpression
get
EnsureChildControls();
return validationExpression;
set
EnsureChildControls();
validationExpression = value;
regularExpressionValidator1.ValidationExpression = value;
regularExpressionValidator1.Enabled = true;
integerValidator.Enabled = false;
decimalValidator.Enabled = false;
#endregion
#region--common--
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
[Description("cssClasses that apply to all validators")]
public string ValidationErrorCssClass
get
EnsureChildControls();
return validationClasses;
set
EnsureChildControls();
validationClasses = value;
requiredFieldValidator1.CssClass = value;
regularExpressionValidator1.CssClass = value;
maxlengthValidator.CssClass = value;
[Bindable(true)]
[Category("Default")]
[DefaultValue("")]
[Localizable(true)]
[Description("Validation group for the textbox and inbuilt validations")]
public string ValidationGroup
get
EnsureChildControls();
return validationGroup;
set
EnsureChildControls();
validationGroup = value;
requiredFieldValidator1.ValidationGroup = value;
regularExpressionValidator1.ValidationGroup = value;
maxlengthValidator.ValidationGroup = value;
textBox1.ValidationGroup = value;
#endregion
#endregion
#region -- blank properties--
public string EmptyText get; set;
public string CommaSeparatedData set; get;
public bool ShowDefaultItem get; set;
public string DropDownCssClass get; set;
#endregion
protected override void RecreateChildControls()
EnsureChildControls();
protected override void CreateChildControls()
Controls.Clear();
#region--textbox--
textBox1 = new TextBox();
textBox1.ID = "textbox1";
//textBox1.CssClass = TextBoxClass;
textBox1.Style[htmlTextWriterStyle.VerticalAlign] = "middle";
//if (!validationGroup.IsNullOrEmpty())
//
// textBox1.ValidationGroup = validationGroup;
//
#endregion
#region--required field validator--
requiredFieldValidator1 = new RequiredFieldValidator();
requiredFieldValidator1.ID = "validator1";
requiredFieldValidator1.ErrorMessage = RequiredErrorMessage;
requiredFieldValidator1.CssClass = validationClasses;
requiredFieldValidator1.Display = ValidatorDisplay.Dynamic;
requiredFieldValidator1.ControlToValidate = textBox1.ID;
requiredFieldValidator1.Enabled = false;
requiredFieldValidator1.SetFocusOnError = true;
//if (isRequired)
//
// requiredFieldValidator1.Enabled = true;
//
//if (!validationGroup.IsNullOrEmpty())
//
// requiredFieldValidator1.ValidationGroup = validationGroup;
//
#endregion
#region-- regular expression validator--
regularExpressionValidator1 = new RegularExpressionValidator();
regularExpressionValidator1.ID = "validator2";
regularExpressionValidator1.Enabled = false;
regularExpressionValidator1.ErrorMessage = RegularExpressionErrorMessage;
regularExpressionValidator1.CssClass = validationClasses;
regularExpressionValidator1.Display = ValidatorDisplay.Dynamic;
regularExpressionValidator1.ControlToValidate = textBox1.ID;
regularExpressionValidator1.SetFocusOnError = true;
//if (!validationGroup.IsNullOrEmpty())
//
// regularExpressionValidator1.ValidationGroup = validationGroup;
//
#endregion
#region -- maxlength validation --
maxlengthValidator = new RegularExpressionValidator();
maxlengthValidator.ControlToValidate = textBox1.ID;
maxlengthValidator.ID = "validator3";
maxlengthValidator.Enabled = false;
maxlengthValidator.CssClass = validationClasses;
maxlengthValidator.Display = ValidatorDisplay.Dynamic;
maxlengthValidator.SetFocusOnError = true;
//if (!validationGroup.IsNullOrEmpty())
//
// maxlengthValidator.ValidationGroup = validationGroup;
//
#endregion
#region--integer Validation--
integerValidator = new RegularExpressionValidator();
integerValidator.ID = "integervalidator";
integerValidator.Enabled = false;
integerValidator.ErrorMessage = InvalidIntegerErrorMessage;
integerValidator.CssClass = validationClasses;
integerValidator.Display = ValidatorDisplay.Dynamic;
integerValidator.ControlToValidate = textBox1.ID;
integerValidator.SetFocusOnError = true;
integerValidator.ValidationExpression=@"^\d+$";
#endregion
#region -- decimal validation--
decimalValidator = new RegularExpressionValidator();
decimalValidator.ID = "decimalvalidator";
decimalValidator.Enabled = false;
decimalValidator.ErrorMessage = InvalidDecimalErrorMessage;
decimalValidator.CssClass = validationClasses;
decimalValidator.Display = ValidatorDisplay.Dynamic;
decimalValidator.ControlToValidate = textBox1.ID;
decimalValidator.SetFocusOnError = true;
decimalValidator.ValidationExpression = @"(^\d*\.?\d*[1-9]+\d*$)|(^[1-9]+\d*\.\d*$)";
#endregion
this.Controls.Add(textBox1);
this.Controls.Add(requiredFieldValidator1);
this.Controls.Add(regularExpressionValidator1);
this.Controls.Add(maxlengthValidator);
this.Controls.Add(integerValidator);
this.Controls.Add(decimalValidator);
protected override void OnLoad(EventArgs e)
EnsureChildControls();
base.OnLoad(e);
protected override void Render(HtmlTextWriter writer)
AddAttributesToRender(writer);
textBox1.RenderControl(writer);
requiredFieldValidator1.RenderControl(writer);
regularExpressionValidator1.RenderControl(writer);
maxlengthValidator.RenderControl(writer);
integerValidator.RenderControl(writer);
decimalValidator.RenderControl(writer);
【问题讨论】:
> “理想情况下它应该有效。但它没有。”你这是什么意思? 【参考方案1】:我无法重现该问题。复合控件确实实现了INamingContainer
,但这不会影响验证组。您能否提供一个小代码示例来帮助我们解决问题?
这是对我有用的代码:
复合控制
public class RequiredTextBox : CompositeControl
private TextBox _textBox = new TextBox ID = "T" ;
private RequiredFieldValidator _validator =
new RequiredFieldValidator ID = "V", ControlToValidate = "T", ErrorMessage = "*" ;
public string Text
get return _textBox.Text;
set _textBox.Text = value;
public string ValidationGroup
get return _validator.ValidationGroup;
set _validator.ValidationGroup = value;
protected override void CreateChildControls()
this.Controls.Add(_textBox);
this.Controls.Add(_validator);
ASPX
<form id="form1" runat="server">
<asp:ValidationSummary runat="server" ID="ValidationSummary" />
<ctl:RequiredTextBox runat="server" ID="TextBox" ValidationGroup="VG" />
<asp:Button runat="server" ID="SubmitButton" Text="Submit" ValidationGroup="VG" />
</form>
【讨论】:
我按照你的显示重新做了代码。它终于起作用了。可能是我做错了什么。 你能帮我做一件事吗?我看到您已经为表单上的自定义控件提供了 ID“TextBox”。当我这样做时,控件的客户端脚本将不起作用,但服务器端验证有效。当我没有给控件(在表单上)提供 ID 时,客户端和服务器验证都将起作用。如果你愿意,我可以发布我的代码。 是的,请提供您的代码。我用我的代码测试了客户端和服务器端验证,它似乎工作。 有一个错误:在你的Render
方法中删除对AddAttributesToRender
的调用。 (这导致<input>
元素获得两个 id
属性,这是无效的HTML。)【参考方案2】:
试试这个:
[ValidationProperty("Text")]
[DefaultProperty("Text")]
[ToolboxData("<0:Class1 runat=server></0:Class1>")]
public class Class1: CompositeControl
private TextBox txtbox = new TextBox();
private RequiredFieldValidator rfv = new RequiredFieldValidator();
public string Text
//this will trigger validator inside
get
this.rfv.Validate();
return this.txtbox.Text; //you may need too loop each textbox to check if it's empty and return empty string, if so.
现在按钮触发复合控件内的验证器。我试过了,成功了。
【讨论】:
【参考方案3】:我不知道为什么会发生这种情况的答案,但是您可以通过向控件添加一个公共方法来解决问题,该方法将其验证作为布尔值返回,然后在页面中添加一个 CustomValidator
并放入类似:
args.IsValid = yourControl.publicMethod()
在其中,我现在无法测试它,但我敢打赌它应该可以工作。
【讨论】:
不幸的是,我们的想法是只在复合控件内部使用验证器。这就是我构建复合控件的原因!以上是关于如何验证复合控件的主要内容,如果未能解决你的问题,请参考以下文章
如何对 jsf 复合组件中的集合属性进行 bean 验证,约束不会触发