Ogłaszanie zwrotne ASP.NET za pomocą JavaScript

81

Mam kilka małych, divktóre jQueryużywają draggable. Są divone umieszczane w pliku UpdatePanel, a na dragstop używam _doPostBack()funkcji JavaScript, w której wydobywam niezbędne informacje z formularza strony.

Mój problem polega na tym, że kiedy wywołuję tę funkcję, cała strona jest ponownie ładowana, ale chcę tylko załadować ponownie panel aktualizacji.

ErnieStings
źródło
Czy wszystkie Twoje elementy DIV mają unikalny identyfikator?
Nathan Taylor

Odpowiedzi:

228

Oto kompletne rozwiązanie

Cały tag formularza strony asp.net

<form id="form1" runat="server">
    <asp:LinkButton ID="LinkButton1" runat="server" /> <%-- included to force __doPostBack javascript function to be rendered --%>

    <input type="button" id="Button45" name="Button45" onclick="javascript:__doPostBack('ButtonA','')" value="clicking this will run ButtonA.Click Event Handler" /><br /><br />
    <input type="button" id="Button46" name="Button46" onclick="javascript:__doPostBack('ButtonB','')" value="clicking this will run ButtonB.Click Event Handler" /><br /><br />

    <asp:Button runat="server" ID="ButtonA" ClientIDMode="Static" Text="ButtonA" /><br /><br />
    <asp:Button runat="server" ID="ButtonB" ClientIDMode="Static" Text="ButtonB" />
</form>

Cała zawartość klasy związanej z kodem strony

Private Sub ButtonA_Click(sender As Object, e As System.EventArgs) Handles ButtonA.Click
    Response.Write("You ran the ButtonA click event")
End Sub

Private Sub ButtonB_Click(sender As Object, e As System.EventArgs) Handles ButtonB.Click
    Response.Write("You ran the ButtonB click event")
End Sub
  • Element LinkButton jest dołączony, aby zapewnić, że funkcja javascript __doPostBack jest renderowana do klienta. Samo posiadanie kontrolek Button nie spowoduje renderowania tej funkcji __doPostBack. Ta funkcja będzie renderowana ze względu na różnorodne kontrolki na większości stron ASP.NET, więc pusty przycisk linku zwykle nie jest potrzebny

Co się dzieje?

Klientowi są renderowane dwie kontrolki wejściowe:

<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
  • __EVENTTARGET otrzymuje argument 1 z __doPostBack
  • __EVENTARGUMENT otrzymuje argument 2 z __doPostBack

Funkcja __doPostBack jest renderowana w następujący sposób:

function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
  • Jak widać, przypisuje wartości do ukrytych wejść.

Po przesłaniu formularza / ogłoszeniu zwrotnym:

  • Jeśli podałeś UniqueID przycisku sterującego serwerem, którego moduł obsługi kliknięcia przycisku chcesz uruchomić ( javascript:__doPostBack('ButtonB','')wówczas zostanie uruchomiony moduł obsługi kliknięcia przycisku dla tego przycisku.

Co jeśli nie chcę uruchamiać modułu obsługi kliknięć, ale zamiast tego chcę zrobić coś innego?

Możesz przekazać, co chcesz, jako argumenty __doPostBack

Następnie możesz przeanalizować ukryte wartości wejściowe i odpowiednio uruchomić określony kod:

If Request.Form("__EVENTTARGET") = "DoSomethingElse" Then
    Response.Write("Do Something else") 
End If

Inne notatki

  • Co się stanie, jeśli nie znam identyfikatora kontrolki, której program obsługi kliknięć chcę uruchomić?
    • Jeśli nie jest to możliwe do przyjęcia zestawu ClientIDMode="Static", można zrobić coś takiego: __doPostBack('<%= myclientid.UniqueID %>', '').
    • Lub: __doPostBack('<%= MYBUTTON.UniqueID %>','')
    • Spowoduje to wstrzyknięcie unikalnego identyfikatora kontrolki do javascript, jeśli sobie tego życzysz
Brian Webster
źródło
48
+1 za kompletność. Coś świetnych odpowiedzi, które sprawiają, że uwielbiam StackOverflow.
Manitra Andriamitondra
3
To jedno z najlepszych wyjaśnień dla __doPostBack (), jakie kiedykolwiek spotkałem. +10 do tego!
GuruC
1
@BrianWebster, Wielkie dzięki za twój szczegółowy post. Czy mógłbym zasugerować każdemu, kto nadal korzysta z programu ASP.NET 3.5 i starszych, używając języka C # zamiast VB.NET, zmienia ostatnie dwa wiersze w pliku .aspx na następujące? <asp: Button runat = "server" ID = "ButtonA" Text = "ButtonA" OnClick = "ButtonA_Click" /> <br /> <br /> <asp: Button runat = "server" ID = "ButtonB" Text = "ButtonB" OnClick = "ButtonB_Click" />
yangli.liy
1
To bardzo pomocne rozwiązanie. Jeśli korzystasz ze stron wzorcowych, identyfikatory przycisków są nieco zaciemniane. Zobacz odpowiedź użytkownika489998 poniżej, aby uzyskać pomoc w uzyskaniu prawidłowego identyfikatora dla ogłaszania zwrotnego.
DCastenholz
1
@BrianWebster Naprawdę rzadko zdarza się, aby ktoś był w stanie zapewnić kompletne rozwiązanie czyjegoś problemu ORAZ zapewnić odpowiednie alternatywy dla potencjalnych odchyleń.
GoldBishop
15

Per Phairoh: Użyj tego na stronie / komponencie na wypadek zmiany nazwy panelu

<script type="text/javascript">
     <!--
     //must be global to be called by ExternalInterface
         function JSFunction() {
             __doPostBack('<%= myUpdatePanel.ClientID  %>', '');
         }
     -->
     </script>
Laramie
źródło
10

O ile rozwiązanie Phairoh wydaje się teoretycznie trafne, o tyle znalazłem też inne rozwiązanie tego problemu. Przekazując identyfikator UpdatePanels jako parametr (cel zdarzenia) dla funkcji doPostBack, panel aktualizacji odeśle z powrotem, ale nie całą stronę.

__doPostBack('myUpdatePanelId','')

* uwaga: drugi parametr służy do dodawania argumentów zdarzeń

mam nadzieję, że to komuś pomoże!

EDYCJA: wygląda na to, że ta sama rada została podana powyżej, gdy pisałem :)

ErnieStings
źródło
2
To zadziała i zrobiłem coś podobnego w aplikacji, ale to naprawdę nie jest dobry pomysł i nienawidzę, że musiałem to zrobić, kiedy to zrobiłem. Jeśli nazwa panelu aktualizacji kiedykolwiek się zmieni, to zepsuje się. Jeśli kiedykolwiek umieścisz to w kontrolce użytkownika, zepsuje się. Jeśli dodasz masterpage, zepsuje się. Tak, działa, ale jest dość delikatny. Przynajmniej użyj właściwości ClientId panelu aktualizacji zamiast statycznego ciągu znaków.
phairoh
9

Używanie __doPostBackbezpośrednio jest baaardzo XXI wieku. Każdy, kto koduje WebForms w 2018 roku, używa GetPostBackEventReference

(Poważniej jednak, dodanie tego jako odpowiedzi na kompletność. Używanie __doPostBackbezpośrednio jest złą praktyką (pojedynczy prefiks podkreślony zwykle wskazuje członka prywatnego, a podwójny oznacza bardziej uniwersalnego członka prywatnego), chociaż prawdopodobnie nie zmieni się ani nie stanie się przestarzały w tym punkt. Mamy w pełni obsługiwany mechanizm w ClientScriptManager.GetPostBackEventReference .)

Zakładając, że twój btnRefresh znajduje się w naszym UpdatePanel i powoduje ogłaszanie zwrotne, możesz użyć GetPostBackEventReference w następujący sposób ( inspiracja ):

function RefreshGrid() {
    <%= ClientScript.GetPostBackEventReference(btnRefresh, String.Empty) %>;
}
mlhDev
źródło
To działa bardzo dobrze. W mojej sytuacji mogę zadeklarować docelowe kontrolki AJAX do odświeżenia po kliknięciu btnRefresh w znaczniku HTML. Korzystając z tego, bardzo łatwo było to zaimplementować dzięki obsłudze AJAX.
DanielG
6

Jeśli ktoś ma z tym problem (tak jak ja), możesz uzyskać kod postback dla przycisku, dodając do niego atrybut UseSubmitBehavior = "false". Jeśli zbadasz wyrenderowane źródło przycisku, zobaczysz dokładny javascript, który musisz wykonać. W moim przypadku była to nazwa przycisku, a nie identyfikator.

user489998
źródło
Bardzo przydatne w przypadku korzystania ze stron wzorcowych.
DCastenholz
1
__doPostBack wydaje się zawsze używać nazwy przycisku podczas korzystania ze stron wzorcowych.
Dennis T - Przywróć Monikę -
2

Czy próbowałeś przekazać identyfikator klienta panelu aktualizacji do funkcji __doPostBack? Mój zespół zrobił to, aby odświeżyć panel aktualizacji i, o ile wiem, zadziałał.

__doPostBack(UpdatePanelClientID, '**Some String**');
Jeremy Bade
źródło
1

Po pierwsze, nie używaj paneli aktualizacji. Są drugą najgorszą rzeczą, jaką Microsoft kiedykolwiek stworzył dla twórców stron internetowych.

Po drugie, jeśli musisz użyć paneli aktualizacji, spróbuj ustawić właściwość UpdateMode na warunkowe. Następnie dodaj wyzwalacz do kontrolki Asp: Hidden, którą dodajesz do strony. Przypisz zdarzenie zmiany jako wyzwalacz. W zdarzeniu dragstop zmień wartość ukrytej kontrolki.

To nie jest testowane, ale teoria wydaje się rozsądna ... Jeśli to nie zadziała, możesz spróbować tego samego z przyciskiem asp:, po prostu ustaw styl display: none i użyj zdarzenia click zamiast zdarzenia change.

phairoh
źródło
7
jaka jest pierwsza najgorsza rzecz, którą Microsoft stworzył dla twórców stron internetowych?
ErnieStings
2
kontrola logowania musi znajdować się dość wysoko na tej liście.
kim3er
1
Czy możesz wyjaśnić, dlaczego UpdatePanels jest tak zła? Jeśli tak jest, chciałbym przeczytać kilka powodów, dla których ich nie używać. Jak dotąd nie natknąłem się na żadne kluczowe problemy z UpdatePanels.
Jan Kukacka
@JanKukacka To kiepska abstrakcja AJAX. Umiejętności, których nauczysz się podczas pisania paneli aktualizacji, nie przekładają się bezpośrednio na możliwość prawidłowego wykorzystania AJAX w czymkolwiek poza formularzami sieci Web ASP.NET. UpdatePanels są trudne do debugowania. A jeśli masz włączony ViewState, duża ilość danych jest niepotrzebnie przesyłana do / z serwera, co powoduje duże obciążenie pasma. Nauka prawidłowego AJAX (być może z pewną lekką warstwą abstrakcji, taką jak jQuery) jest znacznie lepszym rozwiązaniem, gdy musisz rozmawiać z serwerem bez wykonywania ogłaszania zwrotnego.
mason
1

Nie możesz zadzwonić, _doPostBack()ponieważ wymusza to złożenie formularza. Dlaczego nie wyłączysz opcji PostBackna UpdatePanel?

Alex Rodrigues
źródło
1
Pytanie. Po przeciągnięciu elementu DIV _doPostBack jest wywoływany przez Ciebie lub automatycznie przez ASP.NET?
Alex Rodrigues
jest wywoływany przeze mnie za pośrednictwem javascript
ErnieStings,