12 Stimmen

Ich muss in asp.net zweimal auf die Schaltfläche klicken (nach dem Textfeld "Autopostback")

Auf einer Seite habe ich:

<asp:TextBox runat="server" ID="EmailTextBox" AutoPostBack="true" OnTextChanged="EmailTextBox_Changed" />
<asp:Button runat="server" ID="SearchButton" OnClick="AddButton_Click" Text="add" />

In EmailTextBox_Changed wird gezählt, wie viele E-Mails gefunden werden können, bevor die Suche gestartet wird.

Das Problem ist, dass Sie, wenn Sie etwas in die EmailTextBox eingeben und auf die Schaltfläche klicken, zweimal klicken müssen, um die tatsächlichen Ergebnisse zu erhalten. Das liegt daran, dass der erste Klick den "AutoPostBack"-Teil des Textfeldes ausführt, und dann muss man erneut klicken, um den tatsächlichen Klick Postback zu machen.

Wie kann ich verhindern, dass unter diesen Umständen zwei Klicks erforderlich sind, ohne die Option "AutoPostBack=true" zu entfernen?

0 Stimmen

Ändern Sie die Schaltfläche von einem Server-Steuerelement zu einer Client-basierten Schaltfläche, zusätzlich verwenden Sie JS für diese.

2voto

Austin Rhymer Punkte 111

Ich habe auch nach einer Antwort auf diese Frage gesucht. Am Ende habe ich alle autopostback=true entfernt und alle Aktionen mit JavaScript durchgeführt, genau wie Sie.

Eines der Dinge, mit denen ich vor dem JavaScript experimentiert habe, war jedoch etwas, um den Kontrollfokus nach einem Postback beizubehalten. Ich bemerkte, dass das versteckte Feld, das ich verwendet habe, um den Namen des Steuerelements zu speichern, das den letzten Fokus hatte, den Namen der Suchschaltfläche (meine ist eine Speicherschaltfläche) enthält. Also, während ich immer noch nicht sicher, wie man die "Suche" Funktion zu feuern "automatisch", wie es sollte, die im Grunde die Postback-Ereignisse aus dem Textfeld UND die Schaltfläche zusammen nacheinander zu verketten ist, kann ich wissen, dass der Benutzer geklickt, dass die Schaltfläche speichern, bevor die Postback passiert (oder versucht,).

Was Sie also bei Postback haben, ist Ihr Textbox-Ereignis, das ausgelöst wird, und dann die Page_Load-Methode oder eine beliebige Seitenzyklus-Methode, die Sie verwenden möchten, bei der Sie überprüfen können, was das letzte Steuerelement mit dem Fokus war. Mit diesem, gibt es mehrere Möglichkeiten, die Sie implementieren könnte ein Workaround.

Aus der Hand, könnten Sie Code in jedem Ereignis hinzufügen, die von einem Steuerelement autopostback, wie das Textfeld und die Suchschaltfläche, um den Namen des Fokus-Steuerelement zu überprüfen feuert. Wenn das Steuerelement, das zuletzt den Fokus hatte, NICHT die Autopostback-Funktion des Steuerelements ist, die wir ausführen, können wir ein bool auf Seitenebene namens "Run_Controls_Method" auf TRUE setzen, andernfalls auf false. Auf diese Weise wissen wir, dass wir die Postback-Methode des Steuerelements ausführen sollten, das zuletzt den Fokus hatte.

Beim Laden der Seite könnten Sie etwas tun wie:

if (Run_Controls_Method && hdfFocusControl.Value != "")
{
    switch(hdfFocusControl.Value)
    {
        case "btnSearch":
           btnSearch_OnClick(null, null);
           break;
        case etc.
    }
}

Die Art, wie ich hdfHasFocus implementiere, ist:

HTML:

<input id="hdfHasFocus" runat="server" type="hidden" />

HTML-Code dahinter:

protected void Page_PreRender(object sender,EventArgs e)
{
   if (IsPostBack != true)
   {
       //Add the OnFocus event to all appropriate controls on the panel1 panel.         
       ControlManager.AddOnFocus(this.Controls,hdfHasFocus,true);
       //other code...
   }

   ControlManager.SetFocus(this.Controls,hdfHasFocus.Value,true);
}

ControlManager.cs verwandter Code:

        /// <summary>
    /// Adds the onfocus event to the UI controls on the controls in the passed in control list.
    /// </summary>
    /// <param name="controls">The list of controls to apply this event.</param>
    /// <param name="saveControl">The control whose .value will be set to the control.ID of the control which had focus before postback.</param>
    /// <param name="Recurse">Should this method apply onfocus recursively to all child controls?</param>
    public static void AddOnFocus(ControlCollection controls, Control saveControl, bool Recurse)
    {
        foreach (Control control in controls)
        {
            //To make the .Add a bit easier to see/read.
            string action = "";

            //Only apply this change to valid control types. 
            if ((control is Button) ||
                (control is DropDownList) ||
                (control is ListBox) ||
                (control is TextBox) ||
                (control is RadDateInput) ||
                (control is RadDatePicker) ||
                (control is RadNumericTextBox))
            {
                //This version ignores errors.  This results in a 'worse case' scenario of having the hdfHasFocus field not getting a 
                //   value but also avoids bothering the user with an error.  So the user would call with a tweak request instead of 
                //   and error complaint.
                action = "try{document.getElementById(\"" + saveControl.ClientID + "\").value=\"" + control.ClientID + "\"} catch(e) {}";

                //Now, add the 'onfocus' attribute and the built action string.
                (control as WebControl).Attributes.Add("onfocus", action);
            }

            //The 'onfocus' event doesn't seem to work for checkbox...use below.
            if (control is CheckBox)
            {
                //This version ignores errors.  This results in a 'worse case' scenario of having the hdfHasFocus field not getting a 
                //   value but also avoids bothering the user with an error.  So the user would call with a tweak request instead of 
                //   and error complaint.
                action = "try{document.getElementById(\"" + saveControl.ClientID + "\").value=\"" + control.ClientID + "\"} catch(e) {}";
                //In case there is already an attribute here for 'onclick' then we will simply try to add to it.
                action = action + (control as WebControl).Attributes["onclick"];

                //Now, add the event attribute and the built action string.                 
                (control as WebControl).Attributes.Add("onclick", action);
            }

            //You don't seem to be able to easily work the calendar button wiht the keyboard, and it seems made for
            //  mouse interaction, so lets set the tab index to -1 to avoid focus with tab.
            if (control is CalendarPopupButton)
            {
                (control as WebControl).Attributes.Add("tabindex", "-1");
            }

            //We also want to avoid user tab to the up and down spinner buttons on any RadNumericTextBox controls.
            if (control is RadNumericTextBox)
            {
                (control as RadNumericTextBox).ButtonDownContainer.Attributes.Add("tabindex", "-1");
                (control as RadNumericTextBox).ButtonUpContainer.Attributes.Add("tabindex", "-1");
            }

            //Recursively call this method if the control in question has children controls and we are told to recurse.
            if ((Recurse) && (control.HasControls()))
            {
                AddOnFocus(control.Controls, saveControl, Recurse);
            }
        }
    }

    /// <summary>
    /// Searches the ControlCollection passed in for a match on the ID name string passed in and sets focus on that control if it is found.
    /// </summary>
    /// <param name="controls">The collection of controls to search.</param>
    /// <param name="FocusToID">The ID of the control to set focus on.</param>
    /// <param name="recurse">Recursively search sub-controls in the passed in control collection?</param>        
    /// <returns>True means keep processing the control list.  False means stop processing the control list.</returns>
    public static bool SetFocus(ControlCollection controls, string FocusToID, bool recurse)
    {
        //Return if no control ID to work with.
        if (string.IsNullOrEmpty(FocusToID) == true)
        { return false; }

        //If we get here and don't have controls, return and continue the other controls if applicable.
        if (controls.Count <= 0)
        { return true; }

        foreach (Control control in controls)
        {
            //If this is the control we need AND it is Enabled, set focus on it.
            if (((control is GridTableRow) != true) &&  //GridTableRow.ClientID throws an error. We don't set focus on a 'Row' anyway.
                (control.ClientID == FocusToID) && 
                ((control as WebControl).Enabled))
            {
                control.Focus();
                //return to caller.  If we were recursing then we can stop now.
                return false;
            }
            else
            {
                //Otherwise, see if this control has children controls to process, if we are told to recurse.
                if ((recurse) && (control.HasControls()))
                {
                    bool _continue = SetFocus(control.Controls, FocusToID, recurse);
                    //If the recursive call sends back false, that means stop.
                    if (_continue != true)
                    { return _continue; }
                }
            }
        }

        //We are done processing all the controls in the list we were given...
        //  If we get here, then return True to the caller.  If this was a recursive call, then
        //  the SetFocus in the call stack above will be told to continue looking since we 
        //  didn't find the control in question in the list we were given.
        return true;
    }

1voto

Tatsächlich müssen Sie nicht auf die Schaltfläche klicken, um das erste Ereignis auszulösen. Verlassen Sie einfach das Textfeld, d. h. mit "Tabulator", um das AutoPostBack-Ereignis auszulösen.

Wenn Sie beides in einem einzigen Postback tun wollen, entfernen Sie einfach die Schaltfläche und tun die Dinge, die Sie in AddButton_Click tun auch in der Textbox_Change-Ereignis.

0 Stimmen

Hm ja, vielleicht. Ich wollte versuchen, zu vermeiden, dass als das Textfeld ein tut nur einen Zähler, und die Schaltfläche tut eine vollständige abrufen.

1voto

Paul Punkte 9129

Eine clientseitige Prüfung war die Lösung für dieses Problem... es scheint keine Möglichkeit zu geben, dies anders zu verhindern.

1voto

Shahid Manzoor Punkte 137

Schreiben Sie den folgenden Code in das Page_Load-Ereignis, um Doppelklicks zu verhindern

BtnSaveAndPrint.Attributes.Add("onclick", "return confirm('Are you sure you Want to Save & Print?');")

0voto

JonH Punkte 31873

Sie könnten dies vermeiden, indem Sie es nicht serverseitig tun und Javascript verwenden. Sie haben auch Ihr Seitenladeereignis nicht gepostet. Überprüfen Sie, ob das Ereignis zurückkommt oder nicht?

Eine andere Möglichkeit, dies zu tun, ist das Ereignis, das auf dem Klick auf die Schaltfläche geschieht, kann aus dem TextChanged-Ereignis aufgerufen werden und loswerden der Schaltfläche alle zusammen.

0 Stimmen

Hm ja, das habe ich mir überlegt. Es gibt tatsächlich mehr Textfelder, und die Autopostback ist dort, so dass Sie eine Anzahl Ihrer Ergebnisse sehen können, wie Sie sie nach unten filtern, und wenn Sie bereit sind, können Sie sie zeigen. Vielleicht ist eine komplett javascriptbasierte Lösung der Weg nach vorne.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X