如何验证复合控件

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 的调用。 (这导致&lt;input&gt; 元素获得两个 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 验证,约束不会触发

Android 片段与复合控件

如何将验证器属性从 JSF2 复合组件传递给 h:inputText?

复合控件选择类

复合控件:选择类