2009-07-29 8 views
2

Ich habe ein Wizard-Steuerelement in meinem ASP.NET-Webformular. Ich gründe die Standard-Schaltfläche auf jeden Schritt in dem ApplicationWizard PreRender Ereignisse in Code-behind etwa so:Festlegen der Standardschaltfläche in Ajaxified Wizard Control

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

Dies ist perfekt funktioniert, aber wenn ich das Wizard-Steuerelement ajaxify funktioniert es nicht. Die Standardschaltfläche wird auf das Steuerelement festgelegt, das ich beim ersten Laden des Formulars (StartNextButton) angegeben habe, aber nicht auf StepNextButton in anderen Schritten. Was mache ich falsch?

Antwort

0

Was ist die Definition einer Standardschaltfläche? Wenn es sich um eine Schaltfläche handelt, die aufgerufen werden soll, wenn Sie sich in einem Textfeld befinden (Eingabetyp = Text) und die Eingabetaste drücken, dann ist dies in jedem Browser eine erste Schaltfläche oder ein Bild im Formular (Eingabetyp = Senden | Bild) wenn vorhanden.

Was Sie tun können, ist ein Clientskript zu allen Steuerelementen hinzuzufügen, für die eine Regel wie das Formular zum Absenden auf [enter] gilt (wie für den Eingabetyp = "text").

Server-Seite Probe (in Form_Init verwendet wird) nur für eine Idee:

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 ist ein Enter-Taste
keyCode == 27 ist ein Escape-Taste

1

Nach ein oder zwei Tage, an denen ich mir die Haare ausreißen konnte ... ich hoffe, das hilft anderen genauso frustriert wie ich:

Jeder, der diesen Beitrag gefunden hat, weiß, dass die intuitive Antwort hier die Standardschaltfläche des Formulars setzt zum nächsten butto n Ihres Assistenten, tut nichts. Der nächste logische Schritt besteht darin, das Problem zu umgehen, indem Sie im Namen des Benutzers auf die Schaltfläche klicken. Es sei angenommen, habe ich die folgenden Handler meine Textbox angebracht innerhalb der Code-Behind und dass myButtonId ist die ID der Schaltfläche I als Standard benötigen:

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

Sie die oben denken würde, würde gut funktionieren, aber wie es stellt sich heraus, das Erzwingen des Wizard-Buttons zum Erstellen eines extrem hinterhältigen Konflikts - der erste Button auf der Seite würde ebenfalls klicken, den ersten Button-Klick überschreiben, den ich per Script erzwingen musste und sehr seltsame Ergebnisse erzeugen. In meinem Fall ist die erste Schaltfläche auf meiner Masterseite eine Schaltfläche mit der Beschriftung Startseite. Wenn der Benutzer darauf klickt, kehrt die Website zur Startseite zurück. Bei meinen Versuchen, den Next-Button des Wizards zu drücken, würde ich sofort wieder auf meiner Homepage landen, für etwas, das überhaupt keinen Grund zu haben schien. Nach dem Anhängen an PageRequestManager.initializeRequest konnte ich sehen, dass ich zwei separate Postbacks hatte: 1 für meinen erzwungenen Wizard-Button und 1 für einen Button, der zu dieser Zeit noch nicht auf meinem Radar war - der Home Page-Button.

Also, kurz gesagt, wenn ich die Standardschaltfläche des Formulars (Page.Form.DefaultButton) aus dem Code hinter aktualisieren, dann dieses Skript aus dem Code dahinter und verweisen Sie es aus meinem Textfeld auch, alles funktioniert just fine:

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

Es ist erwähnenswert, dass ich OnPreRender ist das obige Verfahren aus dem aktiven Assistenten Schritt Ereignisse immer anrufen. Es ist auch erwähnenswert, dass ich nur ein Textfeld pro Schritt in meinem Assistenten hatte, musste ich dieses Verhalten nur einem Steuerelement zuweisen. Ich habe diesen fixen Bereich nicht versucht, um die Eingabetaste auf der ganzen Seite zu drücken, obwohl ich mir nicht vorstellen kann, dass sie sich in diesem Kontext zu unterschiedlich verhalten würde. Sie müssen die Eingabetaste für jedes Steuerelement in Ihrem Assistenten wahrscheinlich nicht abfangen, wenn Sie viele Eingaben pro Schritt haben.

So, da haben Sie es - nur 12 Stunden Fehlersuche, etwas zu tun, das ungefähr 10 Minuten hätte dauern sollen.

Glückliche Kodierung.

B

+0

Ich habe dieses Problem. Ich versuche, basierend auf Ihrer Antwort zu lösen, aber es kann einfach nicht funktionieren. Das Javascript wird zwar hinzugefügt, aber die Seite reagiert immer noch auf die Startseite und nicht auf die nächste Schaltfläche ....? irgendwelche Ideen? –

+0

Hallo @Mad Pierre - hast du mehrere Browser ausprobiert? Meine Antwort hier könnte etwas veraltet sein für Browser wie Chrome, die entschieden haben "click()" kann nicht aufgerufen werden und stattdessen müssen Sie den Mausklick simulieren, indem Sie DOM2-Ereignisse generieren ... – Brian

+0

Noch nicht. Ich versuche zuerst mit IE (9). Hast du meinen anderen Kommentar oben gesehen: Das Skript funktioniert, wenn ich eine Warnung hinzufüge? –

1

Dank Brian half Ihr Skript mir meine eigene Einstellung, wenn RadAjax und mehrere Bedienelemente und mehrere Arten von Platten verwendet wird. Sie können das defaultButton vereinfachen, indem Sie die Schaltflächen-ID vom Steuerelement und nicht im Skript übergeben.

In Seite:

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

In Code:

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 

(Hinweis, UniqueID nicht für mich arbeiten, musste es ClientID ändern)

+0

Dies ist ein komisches! Nachdem ich meinen C# Code auf Ihrem installiert habe, funktioniert der Standard Button nur, wenn ich am Ende der Javascript Funktion eine Warnung habe! dh. Wenn ich setzen Funktion defaultButton (btnid, src, evt) { wenn (evt.keyCode == 13) { var btn = $ get (btnid); setTimeout (neue Funktion() {btn.click();}, 5); Warnung ('Test'); } } Es funktioniert! Das Entfernen der Warnung ("Test") bewirkt jedoch, dass meine Standard-Homepage-Schaltfläche auf "Gewinnen" klickt. Hat jemand irgendwelche Ideen? Das hat für mich bisher ein paar Tage verschwendet ..... –

0

Ich glaube, ich habe endlich geknackt! Die Tatsache, dass eine (Debug) Warnmeldung in dem Javascript es funktionierte, wies mich in die richtige Richtung ...

Ich musste ein paar Zeilen zum Javascript hinzufügen, damit es funktioniert, so dass meine Methode aussieht this:

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

Ich benutze __doPostBack statt klicken, aber das war nicht das Problem.

0

Ich glaube nicht, dass Sie hier Skripterstellung benötigen. Das Problem scheint zu sein, dass auf der Seite mehrere Senden-Schaltflächen vorhanden sind. Sie müssen also asp.net mitteilen, welches Sie als "Standard" einreichen möchten. Und Sie müssen es zum richtigen Zeitpunkt im Seitenlebenszyklus angeben. Ich bin mir nicht sicher, ob es optimal ist, aber es scheint im PreRender-Event zu funktionieren. Ein einfacher ajaxifizierter Assistent mit nur dem folgenden Code scheint die richtige Schaltfläche zu verwenden:

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 
Verwandte Themen