Pregunta

Estoy creando un servidor personalizado de control para generar botón de elementos específicos de marcado y los controladores JavaScript para mi aplicación de Formularios Web forms.Ellos son, por supuesto, capaz de provocar las devoluciones, así que me gustaría que vuelvan a funcionar con cualquiera de ASP controles de validación para la validación de formularios, especialmente en el marco de cliente.

Este botón de control de servidor soporta un OnClientClick la propiedad de emitir un onclick atributo en el botón de la etiqueta con el código provisto (utilizado principalmente por una simple confirmación reprompt cuando un usuario hace clic en un botón de borrar para una vista de lista o similares), por lo que el uso de la asp:Button control del método de emisión de la validación de secuencia de comandos como un atributo onclick va a ser bastante ineficaz.Como cuestión de hecho, la especificación OnClientClick y ValidationGroup los atributos de un estándar asp:Button resulta bastante mal.He aquí una dolorosamente obvio ejemplo de por qué lo que no funciona fuera de la caja:

Marcado De Página

<asp:Button ID="btnSaveAsp" ValidationGroup="vgMyValidationGroup" OnClientClick="return true;" runat="server" />

Marcado Representado

<input type="submit" name="ctl00$cphBodyContent$lvMyList$ctrl0$btnSaveAsp" value="Save"  id="cphBodyContent_lvUsers_btnSaveAsp_0"
    onclick='return true; WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$cphBodyContent$lvMyList$ctrl0$btnSaveAsp", "", true, "vgMyValidationGroup", "", false, false))'>

Aquí es el existente no-código de trabajo para el cableado hasta el control y la validación.No he podido encontrar mucha documentación sobre la mejor manera de lograr esto con un método aparte de la emisión de una similar onclick atributo.Pensé que mi llamada a Page.ClientSCript.RegisterForEventValidation en el reemplazado AddAttributesToRender método de alambre hasta la validación en el cliente, pero que no parece estar funcionando como supuse.Si es necesario, jQuery está disponible para su uso en la unión de manipulación adicional para el evento click del botón:

Servidor Personalizado Botón De Control

<ToolboxData("<{0}:Button runat=server></{0}:Button>")> _
<ParseChildren(False)> _
<PersistChildren(True)> _
Public Class Button
    Inherits System.Web.UI.WebControls.WebControl
    Implements IPostBackDataHandler

    Public Sub New()
        MyBase.New(HtmlTextWriterTag.Button)
    End Sub

    <Category("Behavior")> _
    <DefaultValue("")> _
    Public Overridable Property PostBackUrl As String
        Get
            Return If(ViewState("PostBackUrl"), String.Empty)
        End Get
        Set(value As String)
            ViewState("PostBackUrl") = value
        End Set
    End Property

    <Category("Validation")> _
    <DefaultValue(True)> _
    Public Overridable Property CausesValidation As Boolean
        Get
            Return If(ViewState("CausesValidation"), True)
        End Get
        Set(value As Boolean)
            ViewState("CausesValidation") = value
        End Set
    End Property

    <Category("Validation")> _
    <DefaultValue("")> _
    Public Overridable Property ValidationGroup As String
        Get
            Return If(ViewState("ValidationGroup"), String.Empty)
        End Get
        Set(value As String)
            ViewState("ValidationGroup") = value
        End Set
    End Property

    <Category("Behavior")> _
    <DefaultValue("")> _
    <Description("Client-side script to be run when the button is clicked.")> _
    Public Property OnClientClick As String
        Get
            Return If(ViewState("OnClientClick"), String.Empty)
        End Get
        Set(value As String)
            ViewState("OnClientClick") = value
        End Set
    End Property

    Protected Overrides Sub AddAttributesToRender(writer As HtmlTextWriter)
        MyBase.AddAttributesToRender(writer)

        If Not String.IsNullOrEmpty(OnClientClick) Then
            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, OnClientClick)
        End If

        Dim postBackOptions = GetPostBackOptions()

        If postBackOptions.TargetControl Is Me Then
            writer.AddAttribute(HtmlTextWriterAttribute.Name, ClientID)
        End If

        If Page IsNot Nothing Then
            Page.ClientScript.RegisterForEventValidation(postBackOptions)
        End If
    End Sub

    Protected Overridable Function GetPostBackOptions() As PostBackOptions
        Dim options As New PostBackOptions(Me) With {
            .ClientSubmit = False
        }

        If Page IsNot Nothing Then
            If CausesValidation AndAlso (Page.GetValidators(ValidationGroup).Count > 0) Then
                options.PerformValidation = True
                options.ValidationGroup = ValidationGroup
            End If

            If Not String.IsNullOrEmpty(PostBackUrl) Then
                options.ActionUrl = HttpUtility.UrlPathEncode(ResolveClientUrl(PostBackUrl))
            End If
        End If

        Return options
    End Function
End Class

En la actualidad, este código no funciona con un asp:CompareValidator en el mismo ValidationGroup para determinar si dos de restablecimiento de contraseña campos son iguales antes de la publicación de vuelta al servidor, ni validación de ocurrir una vez que la solicitud se presenta en el lado del servidor.

¿Fue útil?

Solución

Hacer OnClientClick trabajo con el lado del cliente para la validación de formularios

Desde el <asp:Button> control de concatena el valor de OnClientClick con el formulario de validación de secuencia de comandos, la forma más fácil de hacer que funcionen juntos es return false cuando se desea bloquear el envío del formulario, y no hacer nada si desea que el botón para validar y enviar el formulario:

OnClientClick="if (!confirm('Are you sure?')) return false;"

Sin embargo, si usted no desea escribir return confirm('Are you sure?'), a continuación, puede mover el formulario de validación de código para un detector de eventos (como lo sugieren), o usted puede ajustar el OnClientClick un código como este:

writer.AddAttribute(
    HtmlTextWriterAttribute.Onclick,
    "if (!(function() { " + this.OnClientClick + "; return true; })()) return false;" +
    this.Page.ClientScript.GetPostBackEventReference(options, false));

Validación del lado del servidor

Usted necesita para implementar el IPostBackEventHandler interfaz y llamar a la Page.Validate método.El ClientScriptManager.RegisterForEventValidation el método utilizado para la validación de un evento (prevención no autorizados o maliciosos de devoluciones), no para la validación del formulario.

El código de ejemplo (C#)

Aquí está el código para un escueto botón personalizado de control que soporta OnClientClick y ValidationGroup:

[ParseChildren(false)]
[PersistChildren(true)]
public class Button : WebControl, IPostBackEventHandler
{
    private static readonly object EventClick = new object();

    public Button()
        : base(HtmlTextWriterTag.Button)
    {
    }

    public bool CausesValidation
    {
        get { return ((bool?)this.ViewState["CausesValidation"]) ?? true; }
        set { this.ViewState["CausesValidation"] = value; }
    }

    public string ValidationGroup
    {
        get { return (string)this.ViewState["ValidationGroup"] ?? ""; }
        set { this.ViewState["ValidationGroup"] = value; }
    }

    public string OnClientClick
    {
        get { return (string)this.ViewState["OnClientClick"] ?? ""; }
        set { this.ViewState["OnClientClick"] = value; }
    }

    public event EventHandler Click
    {
        add { this.Events.AddHandler(EventClick, value); }
        remove { this.Events.RemoveHandler(EventClick, value); }
    }

    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        base.AddAttributesToRender(writer);
        writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);

        if (this.Page != null && this.Enabled)
        {
            PostBackOptions options = this.GetPostBackOptions();
            writer.AddAttribute(
                HtmlTextWriterAttribute.Onclick,
                this.OnClientClick + this.Page.ClientScript.GetPostBackEventReference(options, false));
        }
    }

    protected virtual PostBackOptions GetPostBackOptions()
    {
        PostBackOptions options = new PostBackOptions(this) { ClientSubmit = false };

        if (this.Page != null)
        {
            if (this.CausesValidation && this.Page.GetValidators(this.ValidationGroup).Count > 0)
            {
                options.PerformValidation = true;
                options.ValidationGroup = this.ValidationGroup;
            }
        }

        return options;
    }

    protected virtual void OnClick(EventArgs e)
    {
        EventHandler handler = (EventHandler)this.Events[EventClick];

        if (handler != null)
        {
            handler(this, e);
        }
    }

    void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
    {
        if (this.CausesValidation)
        {
            this.Page.Validate(this.ValidationGroup);
        }

        this.OnClick(EventArgs.Empty);
    }
}

Otros consejos

Por favor, eche un vistazo a la implementación del botón Framework .NET.Especialmente método addattributeestorender.Luego puede modificar el código para que funcione la forma en que desea:

public class Button : WebControl, IButtonControl, IPostBackEventHandler
{
    private readonly static object EventClick;

    private readonly static object EventCommand;

    [WebSysDescription("Button_CausesValidation")]
    [WebCategory("Behavior")]
    [DefaultValue(true)]
    [Themeable(false)]
    public bool CausesValidation
    {
        get
        {
            object item = this.ViewState["CausesValidation"];
            if (item == null)
            {
                return true;
            }
            else
            {
                return (bool)item;
            }
        }
        set
        {
            this.ViewState["CausesValidation"] = value;
        }
    }

    [Bindable(true)]
    [DefaultValue("")]
    [Themeable(false)]
    [WebCategory("Behavior")]
    [WebSysDescription("WebControl_CommandArgument")]
    public string CommandArgument
    {
        get
        {
            string item = (string)this.ViewState["CommandArgument"];
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item;
            }
        }
        set
        {
            this.ViewState["CommandArgument"] = value;
        }
    }

    [Themeable(false)]
    [WebCategory("Behavior")]
    [WebSysDescription("WebControl_CommandName")]
    [DefaultValue("")]
    public string CommandName
    {
        get
        {
            string item = (string)this.ViewState["CommandName"];
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item;
            }
        }
        set
        {
            this.ViewState["CommandName"] = value;
        }
    }

    [Themeable(false)]
    [WebSysDescription("Button_OnClientClick")]
    [DefaultValue("")]
    [WebCategory("Behavior")]
    public string OnClientClick
    {
        get
        {
            string item = (string)this.ViewState["OnClientClick"];
            if (item != null)
            {
                return item;
            }
            else
            {
                return string.Empty;
            }
        }
        set
        {
            this.ViewState["OnClientClick"] = value;
        }
    }

    [DefaultValue("")]
    [WebCategory("Behavior")]
    [WebSysDescription("Button_PostBackUrl")]
    [Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
    [Themeable(false)]
    [UrlProperty("*.aspx")]
    public string PostBackUrl
    {
        get
        {
            string item = (string)this.ViewState["PostBackUrl"];
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item;
            }
        }
        set
        {
            this.ViewState["PostBackUrl"] = value;
        }
    }

    [WebSysDescription("Button_Text")]
    [WebCategory("Appearance")]
    [DefaultValue("")]
    [Localizable(true)]
    [Bindable(true)]
    public string Text
    {
        get
        {
            string item = (string)this.ViewState["Text"];
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item;
            }
        }
        set
        {
            this.ViewState["Text"] = value;
        }
    }

    [WebSysDescription("Button_UseSubmitBehavior")]
    [WebCategory("Behavior")]
    [DefaultValue(true)]
    [Themeable(false)]
    public bool UseSubmitBehavior
    {
        get
        {
            object item = this.ViewState["UseSubmitBehavior"];
            if (item == null)
            {
                return true;
            }
            else
            {
                return (bool)item;
            }
        }
        set
        {
            this.ViewState["UseSubmitBehavior"] = value;
        }
    }

    [WebSysDescription("PostBackControl_ValidationGroup")]
    [WebCategory("Behavior")]
    [DefaultValue("")]
    [Themeable(false)]
    public string ValidationGroup
    {
        get
        {
            string item = (string)this.ViewState["ValidationGroup"];
            if (item == null)
            {
                return string.Empty;
            }
            else
            {
                return item;
            }
        }
        set
        {
            this.ViewState["ValidationGroup"] = value;
        }
    }

    static Button()
    {
        Button.EventClick = new object();
        Button.EventCommand = new object();
    }

    public Button() : base(47)
    {
    }

    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        bool useSubmitBehavior = this.UseSubmitBehavior;
        if (this.Page != null)
        {
            this.Page.VerifyRenderingInServerForm(this);
        }
        if (!useSubmitBehavior)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
        }
        else
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
        }
        PostBackOptions postBackOptions = this.GetPostBackOptions();
        string uniqueID = this.UniqueID;
        if (uniqueID != null && (postBackOptions == null || postBackOptions.TargetControl == this))
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Name, uniqueID);
        }
        writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
        bool isEnabled = base.IsEnabled;
        string empty = string.Empty;
        if (isEnabled)
        {
            empty = Util.EnsureEndWithSemiColon(this.OnClientClick);
            if (base.HasAttributes)
            {
                string item = base.Attributes["onclick"];
                if (item != null)
                {
                    empty = string.Concat(empty, Util.EnsureEndWithSemiColon(item));
                    base.Attributes.Remove("onclick");
                }
            }
            if (this.Page != null)
            {
                string postBackEventReference = this.Page.ClientScript.GetPostBackEventReference(postBackOptions, false);
                if (postBackEventReference != null)
                {
                    empty = Util.MergeScript(empty, postBackEventReference);
                }
            }
        }
        if (this.Page != null)
        {
            this.Page.ClientScript.RegisterForEventValidation(postBackOptions);
        }
        if (empty.Length > 0)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, empty);
            if (base.EnableLegacyRendering)
            {
                writer.AddAttribute("language", "javascript", false);
            }
        }
        if (this.Enabled && !isEnabled)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
        }
        base.AddAttributesToRender(writer);
    }

    protected virtual PostBackOptions GetPostBackOptions()
    {
        PostBackOptions postBackOption = new PostBackOptions(this, string.Empty);
        postBackOption.ClientSubmit = false;
        if (this.Page != null)
        {
            if (this.CausesValidation && this.Page.GetValidators(this.ValidationGroup).Count > 0)
            {
                postBackOption.PerformValidation = true;
                postBackOption.ValidationGroup = this.ValidationGroup;
            }
            if (!string.IsNullOrEmpty(this.PostBackUrl))
            {
                postBackOption.ActionUrl = HttpUtility.UrlPathEncode(this.ResolveClientUrl(this.PostBackUrl));
            }
            postBackOption.ClientSubmit = !this.UseSubmitBehavior;
        }
        return postBackOption;
    }

    protected virtual void OnClick(EventArgs e)
    {
        EventHandler item = (EventHandler)base.Events[Button.EventClick];
        if (item != null)
        {
            item(this, e);
        }
    }

    protected virtual void OnCommand(CommandEventArgs e)
    {
        CommandEventHandler item = (CommandEventHandler)base.Events[Button.EventCommand];
        if (item != null)
        {
            item(this, e);
        }
        base.RaiseBubbleEvent(this, e);
    }

    protected internal override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        if (this.Page != null && base.IsEnabled)
        {
            if ((!this.CausesValidation || this.Page.GetValidators(this.ValidationGroup).Count <= 0) && string.IsNullOrEmpty(this.PostBackUrl))
            {
                if (!this.UseSubmitBehavior)
                {
                    this.Page.RegisterPostBackScript();
                }
            }
            else
            {
                this.Page.RegisterWebFormsScript();
                return;
            }
        }
    }

    protected virtual void RaisePostBackEvent(string eventArgument)
    {
        base.ValidateEvent(this.UniqueID, eventArgument);
        if (this.CausesValidation)
        {
            this.Page.Validate(this.ValidationGroup);
        }
        this.OnClick(EventArgs.Empty);
        this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
    }

    protected internal override void RenderContents(HtmlTextWriter writer)
    {
    }

    private void System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
    {
        this.RaisePostBackEvent(eventArgument);
    }

    [WebCategory("Action")]
    [WebSysDescription("Button_OnClick")]
    public event EventHandler Click;
    [WebCategory("Action")]
    [WebSysDescription("Button_OnCommand")]
    public event CommandEventHandler Command;
}

Continuando Bui CUIRON Lo que necesitas son estas 2 cosas en tu CS 1:

   protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        bool useSubmitBehavior = this.UseSubmitBehavior;
        if (this.Page != null)
        {
            this.Page.VerifyRenderingInServerForm(this);
        }
        if (useSubmitBehavior)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
        }
        else
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
        }
        PostBackOptions postBackOptions = this.GetPostBackOptions();
        writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text);
        bool isEnabled = base.IsEnabled;
        string firstScript = string.Empty;
        if (isEnabled)
        {
            firstScript = this.EnsureEndWithSemiColon(this.OnClientClick);
            if (base.HasAttributes)
            {
                string strOnClick = base.Attributes["onclick"];
                if (strOnClick != null)
                {
                    firstScript = firstScript + this.EnsureEndWithSemiColon(strOnClick);
                    base.Attributes.Remove("onclick");
                }
            }
            if (!this.AutoPostBack)
            {
                firstScript = this.MergeScript(this.OnClientClick, "return false;");
            }
            if (this.Page != null)
            {
                string postBackEventReference = this.Page.ClientScript.GetPostBackEventReference(postBackOptions, false);
                if (postBackEventReference != null)
                {
                    firstScript = this.MergeScript(firstScript, postBackEventReference);
                }
            }
        }
        if (this.Page != null)
        {
            this.Page.ClientScript.RegisterForEventValidation(postBackOptions);
        }
        if (firstScript.Length > 0)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, firstScript);
        }
        if (this.Enabled && !isEnabled)
        {
            writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
        }
        base.AddAttributesToRender(writer);

y

 protected virtual PostBackOptions GetPostBackOptions()
    {
        PostBackOptions options = new PostBackOptions(this, string.Empty);
        options.ClientSubmit = false;
        if (this.Page != null)
        {
            if (this.CausesValidation && (this.Page.GetValidators(this.ValidationGroup).Count > 0))
            {
                options.PerformValidation = true;
                options.ValidationGroup = this.ValidationGroup;
            }
            if (!string.IsNullOrEmpty(this.PostBackUrl))
            {
                options.ActionUrl = HttpUtility.UrlPathEncode(base.ResolveClientUrl(this.PostBackUrl));
            }
        }
        return options;
    }

options.clientsubmit= false;es el secreto

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top