Frage

Ich erstelle ein benutzerdefiniertes Serversteuerelement, um Schaltflächenelemente mit bestimmten Markups und JavaScript-Handlern für meine Web Forms-Anwendung zu generieren.Sie sind natürlich in der Lage, Postbacks zu verursachen, daher möchte ich, dass sie mit allen ASP-Validierungskontrollen für die Formularvalidierung funktionieren, insbesondere mit dem clientseitigen Framework.

Dieses Button-Server-Steuerelement unterstützt eine OnClientClick Eigenschaft zum Ausgeben eines onclick Attribut im Schaltflächen-Tag mit dem bereitgestellten Code (wird hauptsächlich für eine einfache erneute Bestätigungsaufforderung verwendet, wenn ein Benutzer auf eine Schaltfläche zum Löschen für eine Listenansicht oder ähnliches klickt), also unter Verwendung von asp:Button Die Methode des Controls, das Validierungsskript als Onclick-Attribut auszugeben, wird ziemlich wirkungslos sein.Tatsächlich wird beides angegeben OnClientClick Und ValidationGroup Attribute auf einem Standard asp:Button fällt ziemlich schlecht aus.Hier ist ein schmerzlich offensichtliches Beispiel dafür, warum das nicht sofort funktioniert:

Seitenmarkierung

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

Gerendertes Markup

<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))'>

Hier ist der vorhandene, nicht funktionierende Code zum Verdrahten der Steuerung mit Validierung.Ich konnte nicht viel Dokumentation darüber finden, wie man dies mit einer anderen Methode als der Ausgabe einer ähnlichen Methode am besten bewerkstelligen kann onclick Attribut.Ich dachte, mein Anruf Page.ClientSCript.RegisterForEventValidation im überschriebenen AddAttributesToRender -Methode würde die clientseitige Validierung verkabeln, aber das scheint nicht so zu funktionieren, wie ich angenommen habe.Bei Bedarf steht jQuery zur Verfügung, um zusätzliche Verarbeitung an das Klickereignis der Schaltfläche zu binden:

Benutzerdefinierte Server-Schaltflächensteuerung

<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

Derzeit funktioniert dieser Code nicht mit einem asp:CompareValidator im gleichen ValidationGroup um zu ermitteln, ob zwei Passwort-Reset-Felder gleich sind, bevor sie an den Server zurückgesendet werden, und es findet auch keine Validierung statt, sobald die Anforderung auf der Serverseite eintrifft.

War es hilfreich?

Lösung

Herstellung OnClientClick Arbeiten Sie mit der clientseitigen Formularvalidierung

Seit der <asp:Button> control verkettet den Wert von OnClientClick Mit dem Formularvalidierungsskript können Sie sie am einfachsten zusammenarbeiten lassen return false wenn Sie die Formularübermittlung blockieren möchten und nichts unternehmen möchten, wenn Sie möchten, dass die Schaltfläche das Formular validiert und übermittelt:

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

Wenn Sie jedoch unbedingt schreiben möchten return confirm('Are you sure?'), dann können Sie den Formularvalidierungscode in einen Ereignis-Listener verschieben (wie Sie vorschlagen) oder ihn umschließen OnClientClick Code wie folgt:

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

Serverseitige Formularvalidierung

Sie müssen das implementieren IPostBackEventHandler Schnittstelle und rufen Sie die auf Page.Validate Methode.Der ClientScriptManager.RegisterForEventValidation Die Methode wird zur Ereignisvalidierung (Verhinderung unbefugter oder böswilliger Postbacks) und nicht zur Formularvalidierung verwendet.

Beispielcode (C#)

Hier ist der Code für ein einfaches benutzerdefiniertes Schaltflächensteuerelement, das Folgendes unterstützt OnClientClick Und 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);
    }
}

Andere Tipps

Bitte werfen Sie einen Blick auf die Button-Implementierung im .NET Framework.Insbesondere die AddAttributesToRender-Methode.Anschließend können Sie den Code so ändern, dass er wie gewünscht funktioniert:

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;
}

Fortsetzung von Bui Cuion, was Sie brauchen, sind diese 2 Dinge in Ihrem 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);

Und

 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;ist das Geheimnis

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top