6

我正在尝试利用 jQuery UI(或任何其他对话框插件)来替换默认的确认对话框。StackOverflow 上有很多类似的问题和答案,例如:

jquery 对话框:确认单击提交按钮

然而,在 ASP .NET 中,我需要更多的东西。

由于页面上的一个表单约束,在 ASP .NET 页面上(使用 ASP .NET 3.5)我可以有多个按钮提交相同的表单,并且根据提交的标题信息页面知道哪个控件(按钮)触发了表单提交,并且可以在服务器上调用正确的方法(附加到Button的Click事件的方法)。

如果我使用其他 StackOverflow 答案的解决方案,例如:

        buttons: {
            'Delete all items': function() {
                $(this).dialog('close');
                currentForm.submit();
            },
            'Cancel': function() {
                $(this).dialog('close');
            }
        }

PostBack 不会调用任何事件处理程序。如果我将其替换为:

        buttons: {
            'Delete all items': function() {
                $(this).dialog('close');
                $buttonThatWasConfirmed.click();
            },
            'Cancel': function() {
                $(this).dialog('close');
            }
        }

它将导致无休止的模态对话递归。如何在 ASP .NET 中解决它?

4

6 回答 6

3

作为一个选项:SubmitBehavior="false"用于 Button 控件并在表单的结束标记之前放置脚本:

<script type="text/javascript">
    var originalDoPostBack = __doPostBack;
    __doPostBack = function (sender, args) {
        $("#dialog").dialog({
            modal: true,
            title: "Confirm action",
            buttons: {
                Yes: function () {
                    $(this).dialog("close");
                    originalDoPostBack(sender, args);
                },
                Cancel: function () {
                    $(this).dialog("close");
                }
            }
        });
    };
</script>

如果您只想为特定按钮明确调用确认,您可以使用下面的脚本(可能放在标题中)

function confirmPostBack(sender, args) {
    $("#dialog").dialog({
        modal: true,
        title: "Confirm action",
        buttons: {
            Yes: function () {
                $(this).dialog("close");
                __doPostBack(sender.name, args || "");
            },
            Cancel: function () {
                $(this).dialog("close");
            }
        }
    });
    return false;
}

<asp:Button runat="server" Text="Click Me" OnClientClick="return confirmPostBack(this)" />
于 2012-10-19T19:31:19.377 回答
1

几个月前我不得不解决这个问题。我想在一个表单上有多个按钮,也许在一个取消按钮上加上一个模板化的转发器,并让它们都正确地要求适当的确认,并根据用户操作提交表单或取消。以下控件可以根据需要多次包含在表单中。它继承自System.Web.UI.WebControls.LinkButton并使用控件的 PostbackEventReference 来知道如果确认要提交哪个控件。System.Web.UI.WebControls.Button如果您愿意,该控件可以轻松继承。我选择使用链接按钮,因为它的操作非常类似于按钮 Web 控件,但不会发出<input type=submit>无法在不使用控件适配器的情况下使用 jQuery UI 使用图标设置样式的按钮。

/// <summary>
///     A <see cref="T:System.Web.UI.WebControls.LinkButton"/> with added jQuery UI functionality to provide a modal dialog box to cancel the form submit client side.
/// </summary>
/// <remarks>This class requires the inclusion of jQueryUI</remarks>
[DefaultProperty("Text")]
[ToolboxData("<{0}:jQueryUIConfirmedLinkButton runat=\"server\"></{0}:jQueryUIConfirmedLinkButton>")]
public class jQueryUIConfirmedLinkButton : LinkButton
{
    /// <summary>
    ///     Holds the postback event reference data so that the emitted client script can execute the postback if the user confirms the action.
    /// </summary>
    protected string eventReference = null;

    /// <summary>
    ///     Gets or sets the emitted dialog's ID attribute.
    /// </summary>
    /// <value>
    ///     The dialog's ID attribute.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("dialog")]
    [Localizable(true)]
    public string DialogCssID
    {
        get
        {
            String s = (String)ViewState["DialogCssID"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogCssID"] = value;
        }
    }

    internal protected string DialogID
    {
        get
        {
            return String.Format("{0}_{1}", this.ClientID, DialogCssID);
        }
    }

    /// <summary>
    ///     Gets or sets the content of the dialog. This can be plain text or HTML.
    /// </summary>
    /// <value>
    ///     The HTML or plain text content of the dialog.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("<p>Are you sure?</p>")]
    [Localizable(true)]
    public string DialogContent
    {
        get
        {
            String s = (String)ViewState["DialogContent"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogContent"] = value;
        }
    }

    /// <summary>
    ///     Gets or sets the title that will appear on the dialog.
    /// </summary>
    /// <value>
    /// The dialog's title.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("Confirm Action")]
    [Localizable(true)]
    public string DialogTitle
    {
        get
        {
            String s = (String)ViewState["DialogTitle"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogTitle"] = value;
        }
    }

    /// <summary>
    ///     Gets or sets the text that will appear on the confirmation button.
    /// </summary>
    /// <value>
    ///     The text that will appear on dialog's confirmation button.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("Yes")]
    [Localizable(true)]
    public string DialogConfirmButtonText
    {
        get
        {
            String s = (String)ViewState["DialogConfirmButtonText"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogConfirmButtonText"] = value;
        }
    }

    /// <summary>
    ///     Gets or sets the text that will appear on the dialog's rejection button.
    /// </summary>
    /// <value>
    ///     The text that appears on the dialog's rejection button.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("No")]
    [Localizable(true)]
    public string DialogRejectButtonText
    {
        get
        {
            String s = (String)ViewState["DialogRejectButtonText"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogRejectButtonText"] = value;
        }
    }

    /// <summary>
    ///     Raises the <see cref="E:System.Web.UI.Control.Load" /> event. Emits the necessary client script for the control to function.
    /// </summary>
    /// <param name="e">The <see cref="T:System.EventArgs" /> object that contains the event data.</param>
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.eventReference = Page.ClientScript.GetPostBackEventReference(this, string.Empty);
        Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("{0}{1}", this.ClientID, "-DialogScript"), this.GetClientScript(), true);
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), string.Format("{0}{1}", this.ClientID, "-DialogShowScript"), string.Format("function {0}Confirm() {{$('#{0}').dialog('open');}}", this.DialogID), true);
        this.OnClientClick = String.Format("{0}Confirm();return false;", this.DialogID);
    }

    /// <summary>
    ///     Renders the contents of the control to the specified writer. Adds the dialog HTML container to the output stream.
    /// </summary>
    /// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter" /> object that represents the output stream to render HTML content on the client.</param>
    protected override void RenderContents(HtmlTextWriter writer)
    {
        base.RenderContents(writer);
        writer.AddAttribute("id", this.DialogID);
        writer.RenderBeginTag("div");
        writer.Write(this.DialogContent);
        writer.RenderEndTag();
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        base.RenderEndTag(writer);
    }

    /// <summary>
    ///     Gets the client script.
    /// </summary>
    /// <returns>A string that will be output to the client as script</returns>
    private string GetClientScript()
    {
        return string.Format(@"$(function () {{

                            $('#{0}').dialog({{
                                autoOpen: false,
                                modal: true,
                                resizable: false,
                                buttons: {{
                                    '{1}': function () {{
                                        $(this).dialog('close');
                                        eval({2});
                                    }},
                                    '{3}': function () {{
                                        $(this).dialog('close');
                                    }}
                                }},
                                title: '{4}'
                            }});
                          }});", this.DialogID, this.DialogConfirmButtonText, this.eventReference, this.DialogRejectButtonText, this.DialogTitle);
    }
}
于 2012-12-24T15:43:47.553 回答
1

我最近使用过这个,虽然它只适用于链接按钮。如果您愿意,您可以将它们(毕竟它们只是锚)设置为看起来像 html 按钮。

js

$(function () {
    $("#confirmMe").click(function (e) {
        e.preventDefault();
        var $anchor = $(this);
        $("<div>Are you sure you want to do that?</div>").dialog({
            title: "Confirm",
            modal: true,
            buttons: {
                "Ok": function () {
                    window.location = $anchor.attr("href");
                },
                "Cancel": function () {
                    $(this).dialog("close");
                }
            }
        });
    });
});

.net 标记(如果单击确定,将引发确认Me_Click 事件)

<asp:LinkButton Text="Open Me" runat="server" ID="confirmMe" 
    ClientIDMode="Static" onclick="confirmMe_Click" />
于 2012-10-20T00:07:33.573 回答
1

这些是我的两分钱,适用于我的项目:

    // Initialices the behaviour when the page is ready
    $(function() {
        // Sets the function to be called when the confirmation button is pressed          
        $('.jqConfirmacionBorrar').click(function(e) {
            // Prevents the default behaviour of the button
            e.preventDefault();
            // Gets the name of the button that was clicked
            var ControlClickedName = $(this).attr('name');
            // Sets up the dialog to be called, with some custom parameters.
            // The important one is to do the postback call when the confirmation
            // button ('Aceptar' in spanish) is clicked.
            $("#DivConfirmacion").dialog({
                width: 650,
                modal: true,
                draggable: true,
                autoOpen: false,
                buttons: {
                    'Cancelar': function() {
                        $(this).dialog('close');
                        return false;
                    },
                    'Aceptar': function() {
                        $(this).dialog('close');
                        __doPostBack(ControlClickedName, '');
                        return true;
                    }
                }
            });
            // Opens the dialog to propt the user for confirmation
            $('#DivConfirmacion').dialog('open');
        });
    });
于 2013-06-15T16:37:27.453 回答
0

不久前我想出了这项工作,所以不确定它是否仍然与最新的 jquery-ui 对话框插件保持同步,但你明白了。它使(不幸的)用于eval执行 javascript asp.net 生成以提交放置在锚的 href 中的表单。你只需要给锚点的 css 类confirm-required

<div class="confirm-dialog ui-helper-hidden" title="Confirm">
    <span class="ui-icon ui-icon-alert"></span>
    <p>Are you sure?</p>
</div>

<script language="javascript" type="text/javascript">

$(function(){
    // call confirm dialog boxes from buttons that require it
    $(".confirm-required:isactive").click(function () {
        var callback = $(this).attr("href");
        return showConfirmDialog(callback);
    });
});

this.showConfirmDialog = function (callback) {
    $(".confirm-dialog").dialog("destroy");
    $(".confirm-dialog").dialog({
        autoOpen: true,
        modal: true,
        buttons: {
            "OK": function () {
                $(this).dialog("close");
                eval(callback);
            },
            "Cancel": function () {
                $(this).dialog("close");
            }
        }
    });

    return false;
};

</script>
于 2012-10-19T17:16:44.163 回答
0

我承认这有点冗长,但以下适用于我能想到的每种情况:

$(document).ready(function () {
    'use strict';
    var getParsedPostback = function getParsedPostback(self) {
        /*
         * self is a jQuery object. The purpose of this function is to extract the
         * __doPostBack function or the WebForm_DoPostBackWithOptions function as a
         * string, parse out the component arguments, and return it as a different
         * function to be used as a callback. If the postback function does not exist
         * as a string (in the case of a submit button, for instance) then the
         * returned callback should unbind any click handlers and then trigger the
         * element's click event.
         */
        var postback = self.data('postback'),
            trimLeft = /^\s+/,
            trimRight = /\s+$/,
            startingQuote = /^['"]/,
            endingQuote = /['"]$/,
            eventTarget,
            eventArgument,
            validation,
            validationGroup,
            actionUrl,
            trackFocus,
            clientSubmit;
        if (postback.substring(postback.length - 1, postback.length) === ';') {
            //remove the trailing ";"
            postback = postback.substring(0, postback.length - 1);
        }
        if (postback.indexOf('javascript:') === 0) {
            //remove the "javascript:"
            postback = postback.substring(('javascript:').length, postback.length - 1);
        }
        //in case postback is in the form __doPostBack(&#39;XXXXXX&#39;,&#39;XXXXXX&#39;)
        postback = decodeURIComponent(postback);
        //parse by case
        if (postback.indexOf('__doPostBack(') === 0) {
            //postback should now be __doPostBack('XXXXXX','XXXXXX')
            postback = postback.substring(('__doPostBack(').length, postback.length - 2);
            postback = postback.split(',');
            eventTarget = encodeURIComponent(postback[0].replace(startingQuote, '').replace(endingQuote, ''));
            eventArgument = encodeURIComponent(postback[1].replace(startingQuote, '').replace(endingQuote, ''));
            postback = function () {
                __doPostBack(eventTarget, eventArgument);
            };
        } else if (postback.indexOf('WebForm_DoPostBackWithOptions(') === 0) {
            //postback should now be WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions('XXXXXX', 'XXXXXX', 'XXXXXX', 'XXXXXX', 'XXXXXX'))
            postback = postback.substring(('WebForm_DoPostBackWithOptions(').length, postback.length - 2);
            postback = postback.split(',');
            eventTarget = encodeURIComponent(postback[0].replace(startingQuote, '').replace(endingQuote, ''));
            eventArgument = encodeURIComponent(postback[1].replace(startingQuote, '').replace(endingQuote, ''));
            validation = !!postback[2].replace(startingQuote, '').replace(endingQuote, '');     //use !! to convert string to boolean
            validationGroup = encodeURIComponent(postback[3].replace(startingQuote, '').replace(endingQuote, ''));
            actionUrl = encodeURIComponent(postback[4].replace(startingQuote, '').replace(endingQuote, ''));
            trackFocus = !!postback[5].replace(startingQuote, '').replace(endingQuote, '');     //use !! to convert string to boolean
            clientSubmit = !!postback[6].replace(startingQuote, '').replace(endingQuote, ''); //use !! to convert string to boolean
            postback = function () {
                __doPostBack(new WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit));
            };
        } else if (postback === 'submit') {
            //no apparent postback handler, must be a submit or an image
            postback = function () {
                //unbind the assigned click handler
                self.unbind('click');
                //trigger the click event
                self.click();
            };
        }
        return postback;
    };
    var clickHandler = function clickHandler(e) {
        var postback = getParsedPostback($(this)); //get the postback as a callback
        $('div#dialog').dialog('option', {
            "buttons": {
                "Delete all items": function () {
                    $(this).dialog('close');
                    postback(); //call the postback
                },
                "Cancel": function () {
                    $(this).dialog('close');
                }
            }
        }).dialog('open');
        e.preventDefault();
        return false;
    };
    var storePostbacks = function storePostbacks() {
        /*
         * The purpose of this function is to remove any existing __doPostBack functions
         * or WebForm_DoPostBackWithOptions functions and store them in the "data" for
         * the element. The "getParsedPostback" function above wil make extensive use of
         * the element's "data" to parse a usable callback for postback.
         */
        $('input[type="submit"], input[type="button"], input[type="image"], a[href*="__doPostBack"]').each(function (i, elem) {
            var self = $(elem),
            postback = '';
            if (typeof self.attr('onclick') !== 'undefined') {
                //store the postback in data and remove from the element.
                postback = self.attr('onclick');
                self.removeAttr('onclick').data('postback', postback);
            } else if (typeof self.attr('href') !== 'undefined') {
                //store the postback in data and remove from the element.
                postback = self.attr('href');
                self.attr('href', '#').data('postback', postback);
            } else if (self.attr('type') === 'submit' || self.attr('type') === 'image') {
                //flag as a submit.
                self.data('postback', 'submit');
            }
        });
    };
    storePostbacks();
    $('input#<%#aspButton1.ClientID %>').click(clickHandler);
    $('input#<%#aspButton2.ClientID %>').click(clickHandler);
    $('input#<%#aspImageButton.ClientID %>').click(clickHandler);
    $('a#<%#aspLinkButton.ClientID %>').click(clickHandler);
    $('div#dialog').dialog({
        "autoOpen": false
    });
});

使用带有 jQ​​uery 1.8.2 和 jQueryUI 1.9.0 的 ASP.Net 4.0 框架对以下标记进行了测试:

<body>
    <form id="form1" runat="server">
    <div>
        <div id="dialog">
            <p>Test of dialog.</p>
        </div>
        <div id="controls">
            <asp:Button ID="aspButton1" runat="server" Text="aspButton1" />
            <asp:LinkButton ID="aspLinkButton" runat="server">LinkButton</asp:LinkButton>
            <asp:ImageButton ID="aspImageButton" runat="server" />
            <asp:Button ID="aspButton2" runat="server" Text="aspButton2" />
        </div>
    </div>
    </form>
</body>
于 2012-10-20T16:46:56.863 回答