【问题标题】:Setting Default Button in Ajaxified Wizard Control在 Ajaxified 向导控件中设置默认按钮
【发布时间】:2009-07-29 15:09:32
【问题描述】:

我的 ASP.NET Web 表单上有一个向导控件。我在代码隐藏中的 ApplicationWizard PreRender 事件的每个步骤上设置默认按钮,如下所示:

Page.Form.DefaultButton = ApplicationWizard.FindControl("StepNavigationTemplateContainerID").FindControl("StepNextButton").UniqueID;

这工作得很好,但是当我 ajaxify 向导控件时它不起作用。默认按钮设置为我在初始加载表单(StartNextButton)时指定的控件,但在其他步骤中不会更新为 StepNextButton。我做错了什么?

【问题讨论】:

    标签: asp.net asp.net-ajax wizard


    【解决方案1】:

    在拔掉头发一两天后,我设法解决了这个问题……希望这可以帮助像我一样沮丧的其他人:

    任何发现这篇文章的人都知道这里的直观答案,将表单的默认按钮设置为向导的“下一步”按钮,没有任何作用。因此,下一个合乎逻辑的步骤是通过代表用户单击按钮来尝试围绕问题进行设计。假设我已将以下处理程序从代码隐藏中附加到我的文本框,并且 myButtonId 是我需要作为默认按钮的 id:

                function textKeyDown(e) {
                    if (e.keyCode == 13) {
                        var myBtn = $get(myButtonId);
                        myBtn.click();
                    }
                }
    

    您可能认为上面的操作可以正常工作,但事实证明,强制单击向导按钮会造成极其隐秘的冲突 - 页面上的第一个按钮也会单击,覆盖我强制单击的初始按钮通过脚本并创建非常奇怪的结果。在我的例子中,我的母版页中的第一个按钮是一个显示主页的按钮,当用户单击它时,他们会返回到他们的主页。因此,在我试图强制点击向导的“下一步”按钮时,我最终会回到我的主页,这看起来完全没有理由。在附加到 PageRequestManager.initializeRequest 之后,我可以看到我有两个单独的回发启动:1 个用于我的强制向导按钮单击,1 个用于当时甚至不在我的雷达上的按钮 - 主页按钮。

    所以,长话短说,如果我从后面的代码中更新表单的默认按钮 (Page.Form.DefaultButton),然后从后面的代码中发出这个脚本并从我的文本框中引用它,一切正常很好:

        public static void ExampleAssignDefaultButton(WizardStepBase activeWizardStep, TextBox myTextBox, IButtonControl myButton)
        {
            // create the format string for the script
            string javaScript = @"function defaultButton(src, evt){{
                                    if(evt.keyCode == 13){{
                                        var btn = $get('{0}');
                                        setTimeout(new function() {{ btn.click(); }}, 5);
                                    }}
                                }}";
    
            // format it ...
            javaScript = String.Format(javaScript, ((WebControl)myButton).ClientID);
            // register it...
            ScriptManager.RegisterClientScriptBlock(activeWizardStep, activeWizardStep.GetType(), "defaultButton", javaScript, true);
    
            // assign it to my textbox
            myTextBox.Attributes.Add("onkeydown", "defaultButton(this, event);");
    
            // also update the form's default button:
            myTextBox.Page.Form.DefaultButton = ((WebControl)myButton).UniqueID;
        }
    

    值得注意的是,我总是从活动向导步骤的 OnPreRender 事件中调用上述方法。还值得注意的是,因为我的向导中的每个步骤只有一个文本框,所以我只需将此行为分配给单个控件。我没有尝试过这个修复范围来捕捉整个页面上的 Enter 键按下,尽管我无法想象它在这种情况下的行为会有太大的不同。如果每个步骤有很多输入,您可能不需要在向导中的每个控件上按 Enter 键。

    所以,您已经完成了 - 只需 12 小时的故障排除即可完成本应花费大约 10 分钟的事情。

    编码愉快。

    B

    【讨论】:

    • 我有这个问题。我正在尝试根据您的回答解决问题,但无法使其正常工作。 javascript 添加好,但页面仍然响应主页按钮而不是下一个按钮....?有什么想法吗?
    • 嗨@Mad Pierre - 你试过多个浏览器吗?对于决定无法调用“click()”的 Chrome 等浏览器,我在这里的回答可能稍微过时了,而是您必须通过生成 DOM2 事件来模拟鼠标点击...
    • 还没有。我首先尝试使用 IE(9)。你有没有看到我上面的其他评论:如果我添加警报,脚本工作?
    • 嗨@MadPierre - 也许在 .click() 调用之前禁用你的主页按钮?我必须查看您的代码才能知道到底发生了什么,但是肯定会触发单击您的另一个按钮,并且禁用该按钮将阻止单击被允许触发-编辑-刚刚看到您解决了问题-很高兴搞定了 :) 也许禁用会帮助其他人阅读这个帖子,所以我会保持原状......
    【解决方案2】:

    感谢 Brian,在使用 RadAjax 和多个用户控件以及多种类型的面板时,您的脚本帮助我设置了自己的脚本。您可以通过从控件而不是在脚本中传递按钮 ID 来简化 defaultButton。

    在页面中:

    function defaultButton(btnid, src, evt) {
        if (evt.keyCode == 13) {
            var btn = $get(btnid);
            setTimeout(new function () { btn.click(); }, 5);
        }
    }
    

    在代码中:

    Private Sub WizardStep_PreRender(sender As Object, e As System.EventArgs) Handles wsUserPass.PreRender, wsCompanyCode.PreRender, wsSetPassword.PreRender
        Dim button As WebControl = Nothing
        Dim activeWizardStep As WizardStepBase = CType(sender, WizardStepBase)
        Select Case activeWizardStep.StepType
            Case WizardStepType.Step
                button = activeWizardStep.FindControl("StepNavigationTemplateContainerID").FindControl("StepNextButton")
            Case WizardStepType.Start
                button = activeWizardStep.FindControl("StartNavigationTemplateContainerID").FindControl("StartNextButton")
            Case WizardStepType.Finish
                button = activeWizardStep.FindControl("FinishNavigationTemplateContainerID").FindControl("FinishButton")
        End Select
        If button Is Nothing Then Return
        Dim ctrls = FindControls(Of RadTextBox)(activeWizardStep)
        For Each ctrl In ctrls
            ctrl.Attributes.Add("onkeydown", String.Format("defaultButton('{0}', this, event);", button.ClientID))
        Next
        pnlMain.DefaultButton = button.UniqueID
    End Sub
    
    Public Shared Function FindControls(Of T)(ctrl As Control) As List(Of T)
        Dim controls As New List(Of T)
        If ctrl.Controls.Count > 0 Then
            For Each subctrl In ctrl.Controls
                If [Type].ReferenceEquals(GetType(T), subctrl.GetType()) Then
                    controls.Add(subctrl)
                Else
                    controls.AddRange(FindControls(Of T)(subctrl))
                End If
            Next
        End If
        Return controls
    End Function
    

    (注意,UniqueID 对我不起作用,必须将其更改为 ClientID)

    【讨论】:

    • 这很奇怪!将我的 c# 代码基于您的默认按钮仅当我在 javascript 函数末尾有警报时才有效! IE。如果我把函数 defaultButton(btnid, src, evt) { if (evt.keyCode == 13) { var btn = $get(btnid); setTimeout(new function () { btn.click(); }, 5);警报(“测试”); } } 有用!但是删除警报('test')会导致我的默认主页按钮单击“获胜”。有人有什么想法吗?到目前为止,这对我来说已经浪费了几天.....
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      默认按钮的定义是什么?如果它是一个按钮,当您在文本表单字段(输入类型=文本)并按回车时应该调用它,那么在每个浏览器中它都是表单中的第一个提交或图像按钮(输入类型=提交|图像)如果存在。

      您可以做的是向所有控件添加一个客户端脚本,在 [enter] 上提交表单等规则适用(如在 input type="text" 上)。

      服务器端示例(可在 Form_Init 中使用)仅供参考:

      SomeTextBox.Attributes.Add("onkeydown",
          "if((event.keyCode&&event.keyCode==13)){" +
          Page.ClientScript.GetPostBackEventReference(StepNextButton, "") +
          ";return false;}" +
          "if((event.keyCode&&event.keyCode==27)){" +
          Page.ClientScript.GetPostBackEventReference(CancelButton, "") +
          ";return false;}");
      

      keyCode==13 是 Enter 键
      keyCode==27 是一个退出键

      【讨论】:

        【解决方案5】:

        我想我终于破解了这个! javascript 中的(调试)警报消息使其工作的事实为我指明了正确的方向......

        我必须在 javascript 中添加几行才能让它工作,这样我的方法看起来像这样:

        private void SetDefaultButtonScript(WizardStepBase activeWizardStep, IButtonControl myButton)
            {
                string clientID = ((WebControl)myButton).ClientID;
                string uniqueID = ((WebControl)myButton).UniqueID;
        
                // create the format string for the script 
                string javaScript = @"function defaultButton(btnid, evt) {{ 
                                        if (evt.keyCode == 13) {{ 
                                            __doPostBack('{0}', '');
                                            var btn = $get('{1}');
                                            btn.focus();
                                            return;
                                        }} 
                                    }} 
                                    ";
                javaScript = String.Format(javaScript, uniqueID, clientID); 
        
                // register it... 
                ScriptManager.RegisterClientScriptBlock(activeWizardStep, activeWizardStep.GetType(), "defaultButton", javaScript, true);
        
                foreach (Control c in activeWizardStep.Controls)
                {
                    if (c is TextBox)
                    {
                        ((TextBox)c).Attributes.Add("onkeydown", "defaultButton(this, event);"); 
                    }
                    //TODO child controls of controls to find all text boxes, any other controls etc
                }
        
                Page.Form.DefaultButton = uniqueID;
            } 
        

        我也在使用 __doPostBack 而不是点击,但这不是问题。

        【讨论】:

          【解决方案6】:

          我认为您在这里不需要任何脚本。问题似乎是页面上有多个提交按钮。所以你必须告诉asp.net你想使用哪个作为“默认”提交。你必须在页面生命周期的正确时间告诉它。我不确定它是否是最佳的,但在 PreRender 事件中这样做似乎有效。一个只添加了以下代码的基本 ajaxified 向导似乎使用了正确的按钮:

          Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
              MyBase.OnPreRender(e)
              Select Case LoginWizard.ActiveStep.StepType
                  Case WizardStepType.Start
                      Page.Form.DefaultButton = LoginWizard.FindControl("StartNavigationTemplateContainerID").FindControl("NextStart").UniqueID
                  Case WizardStepType.Step
                      Page.Form.DefaultButton = LoginWizard.FindControl("StepNavigationTemplateContainerID").FindControl("NextStep").UniqueID
                  Case WizardStepType.Finish
                      Page.Form.DefaultButton = LoginWizard.FindControl("FinishNavigationTemplateContainerID").FindControl("LastStep").UniqueID
              End Select
          End Sub
          

          【讨论】:

            猜你喜欢
            • 2023-03-26
            • 1970-01-01
            • 2018-02-27
            • 2016-11-28
            • 1970-01-01
            • 1970-01-01
            • 2020-08-10
            • 2012-08-22
            • 2014-02-25
            相关资源
            最近更新 更多