質問

Web フォーム アプリケーション用の特定のマークアップと JavaScript ハンドラーを含むボタン要素を生成するカスタム サーバー コントロールを作成しています。もちろん、ポストバックを引き起こす可能性があるため、フォーム検証のための ASP の検証コントロール、特にクライアント側のフレームワークで機能するようにしたいと考えています。

このボタン サーバー コントロールは、 OnClientClick を放出するプロパティ onclick 提供されたコードを含む button タグの属性 (主に、ユーザーがリスト ビューなどの削除ボタンをクリックしたときの単純な確認の再プロンプトに使用されます)。 asp:Button onclick 属性として検証スクリプトを発行するコントロールの方法は、非常に効果的ではありません。実際のところ、両方を指定すると、 OnClientClick そして ValidationGroup 規格の属性 asp:Button かなり悪い結果になります。これがそのままでは機能しない理由を示す、痛ましいほど明白な例を次に示します。

ページのマークアップ

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

レンダリングされたマークアップ

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

以下は、検証を使用してコントロールを接続するための既存の機能しないコードです。同様のメッセージを出力する以外の方法でこれを達成する最善の方法についてのドキュメントはあまり見つかりませんでした。 onclick 属性。私は自分の呼びかけをこう思った Page.ClientSCript.RegisterForEventValidation オーバーライドされた状態で AddAttributesToRender このメソッドはクライアント側の検証を接続しますが、それは私が想定したように機能していないようです。必要に応じて、追加の処理をボタンのクリック イベントにバインドする際に jQuery を使用できます。

カスタムサーバーボタンコントロール

<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

現在、このコードは asp:CompareValidator 同じように ValidationGroup サーバーにポストバックする前に 2 つのパスワード リセット フィールドが等しいかどうかを判断します。また、リクエストがサーバー側に到着した後も検証は行われません。

役に立ちましたか?

解決

作る OnClientClick クライアント側のフォーム検証を使用する

以来、 <asp:Button> コントロールは値を連結します OnClientClick フォーム検証スクリプトを使用して、これらを連携させる最も簡単な方法は、次のとおりです。 return false フォームの送信をブロックしたい場合は、ボタンでフォームを検証して送信したい場合は何もしません。

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

ただし、どうしても書きたい場合は、 return confirm('Are you sure?'), 、その後、フォーム検証コードを(あなたが提案したように)イベントリスナーに移動するか、 OnClientClick 次のようなコード:

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

サーバー側のフォーム検証

実装する必要があります IPostBackEventHandler インターフェイスを呼び出して、 Page.Validate 方法。の ClientScriptManager.RegisterForEventValidation このメソッドは、フォームの検証ではなく、イベントの検証 (未承認または悪意のあるポストバックの防止) に使用されます。

サンプルコード(C#)

これは、サポートする必要最低限​​のカスタム ボタン コントロールのコードです。 OnClientClick そして 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);
    }
}

他のヒント

.NET Framework のボタンの実装をご覧ください。特にAddAttributesToRenderメソッド。その後、コードを変更して、希望どおりに動作するようにすることができます。

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

あなたが必要とするものを継続するBui cuionは、あなたのCS 1のこれら2つのことです:

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

そして

 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;秘密です

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top