Udostępnij za pośrednictwem


Objaśnienie wyzwalaczy UpdatePanel ASP.NET AJAX

Autor: Scott Cate

Podczas pracy w edytorze znaczników w programie Visual Studio można zauważyć (z funkcji IntelliSense), że istnieją dwa elementy podrzędne kontrolki UpdatePanel. Jednym z nich jest element Triggers, który określa kontrolki na stronie (lub kontrolki użytkownika, jeśli używasz jednego), który wyzwoli częściowy renderowanie kontrolki UpdatePanel, w którym znajduje się element.

Wprowadzenie

Technologia ASP.NET firmy Microsoft oferuje oparty na zdarzeniach model programowania zorientowany na obiekty i łączy go z zaletami skompilowanego kodu. Jednak jego model przetwarzania po stronie serwera ma kilka wad związanych z technologią, z których wiele może zostać rozwiązanych przez nowe funkcje zawarte w rozszerzeniach microsoft ASP.NET 3.5 AJAX. Rozszerzenia te umożliwiają wiele nowych zaawansowanych funkcji klienta, w tym częściowe renderowanie stron bez konieczności odświeżania pełnej strony, możliwość uzyskiwania dostępu do usług sieci Web za pośrednictwem skryptu klienta (w tym interfejsu API profilowania ASP.NET) oraz rozbudowanego interfejsu API po stronie klienta zaprojektowanego do dublowania wielu schematów sterowania widocznych w zestawie kontroli po stronie serwera ASP.NET.

Ten oficjalny dokument analizuje funkcje wyzwalaczy XML składnika ASP.NET AJAX UpdatePanel . Wyzwalacze XML zapewniają szczegółową kontrolę nad składnikami, które mogą powodować częściowe renderowanie określonych kontrolek UpdatePanel.

Ten oficjalny dokument jest oparty na wersji Beta 2 .NET Framework 3.5 i Visual Studio 2008. Rozszerzenia ASP.NET AJAX, wcześniej zestaw dodatków przeznaczony do ASP.NET 2.0, są teraz zintegrowane z biblioteką klas podstawowych .NET Framework. W tym oficjalnym dokumencie założono również, że będziesz pracować z programem Visual Studio 2008, a nie Visual Web Developer Express, i udostępni wskazówki zgodnie z interfejsem użytkownika programu Visual Studio (chociaż listy kodu będą całkowicie zgodne niezależnie od środowiska deweloperskiego).

Wyzwalacze

Wyzwalacze dla danego elementu UpdatePanel domyślnie automatycznie zawierają wszystkie kontrolki podrzędne, które wywołują powrót, w tym (na przykład) kontrolki TextBox, które mają ich AutoPostBack właściwość ustawioną na wartość true. Jednak wyzwalacze mogą być również uwzględniane deklaratywnie przy użyciu znaczników; odbywa się to w <triggers> sekcji deklaracji kontrolki UpdatePanel. Mimo że wyzwalacze mogą być dostępne za pośrednictwem Triggers właściwości kolekcji, zaleca się zarejestrowanie wszystkich częściowych wyzwalaczy renderowania w czasie wykonywania (na przykład jeśli kontrolka nie jest dostępna w czasie projektowania) przy użyciu RegisterAsyncPostBackControl(Control) metody obiektu ScriptManager dla strony w ramach Page_Load zdarzenia. Pamiętaj, że strony są bezstanowe, dlatego należy ponownie zarejestrować te kontrolki za każdym razem, gdy są tworzone.

Automatyczne dołączanie wyzwalacza podrzędnego można również wyłączyć (dzięki czemu kontrolki podrzędne, które tworzą postbacks, nie wyzwalają automatycznie częściowych renderów), ustawiając ChildrenAsTriggers właściwość na false. Pozwala to na największą elastyczność przypisywania określonych kontrolek, które mogą wywołać renderowanie strony i jest zalecane, aby deweloper zdecydował się reagować na zdarzenie, a nie obsługiwać wszelkich zdarzeń, które mogą wystąpić.

Należy pamiętać, że gdy kontrolki UpdatePanel są zagnieżdżone, gdy właściwość UpdateMode jest ustawiona na wartość Warunkowa, jeśli element podrzędny UpdatePanel zostanie wyzwolony, ale element nadrzędny nie, zostanie odświeżony tylko podrzędny element UpdatePanel. Jeśli jednak nadrzędny element UpdatePanel zostanie odświeżony, zostanie również odświeżony podrzędny element UpdatePanel.

Element <Wyzwalacze>

Podczas pracy w edytorze znaczników w programie Visual Studio można zauważyć (z funkcji IntelliSense), że istnieją dwa elementy podrzędne kontrolki UpdatePanel . Najczęściej widzianym elementem <ContentTemplate> jest element, który zasadniczo hermetyzuje zawartość, która będzie przechowywana przez panel aktualizacji (zawartość, dla której włączamy częściowe renderowanie). Drugim elementem <Triggers> jest element, który określa kontrolki na stronie (lub kontrolki użytkownika, jeśli używasz jednego), który wyzwoli częściowy renderowanie kontrolki UpdatePanel, w którym <znajduje się element Wyzwalacze> .

Element <Triggers> może zawierać dowolną liczbę z dwóch węzłów podrzędnych: <asp:AsyncPostBackTrigger> i <asp:PostBackTrigger>. Obaj akceptują dwa atrybuty i ControlIDEventName, i mogą określić dowolną kontrolkę w bieżącej lekcji hermetyzacji (na przykład jeśli kontrolka UpdatePanel znajduje się w kontrolce użytkownika sieci Web, nie należy próbować odwoływać się do kontrolki na stronie, na której będzie znajdować się kontrolka użytkownika).

Element <asp:AsyncPostBackTrigger> jest szczególnie przydatny w tym, że może dotyczyć dowolnego zdarzenia z kontrolki, która istnieje jako element podrzędny dowolnej kontrolki UpdatePanel w jednostce hermetyzacji, a nie tylko UpdatePanel, w którym ten wyzwalacz jest elementem podrzędnym. W związku z tym można wprowadzić dowolną kontrolkę, aby wyzwolić częściową aktualizację strony.

Podobnie element może służyć do wyzwalania częściowego renderowania strony, ale taki, <asp:PostBackTrigger> który wymaga pełnej zaokrąglonej podróży do serwera. Ten element wyzwalacza może również służyć do wymuszenia renderowania pełnej strony, gdy kontrolka w przeciwnym razie normalnie wyzwoli częściowy renderowanie strony (na przykład gdy Button kontrolka istnieje w <ContentTemplate> elemecie kontrolki UpdatePanel). Ponownie element PostBackTrigger może określić dowolną kontrolkę, która jest elementem podrzędnym dowolnej kontrolki UpdatePanel w bieżącej lekcji hermetyzacji.

<Dokumentacja elementu wyzwalaczy>

Elementy podrzędne znaczników:

Tag Opis
<asp:AsyncPostBackTrigger> Określa kontrolkę i zdarzenie, które spowoduje częściową aktualizację strony dla kontrolki UpdatePanel, która zawiera odwołanie do tego wyzwalacza.
<asp:PostBackTrigger> Określa kontrolkę i zdarzenie, które spowoduje aktualizację pełnej strony (odświeżanie pełnej strony). Ten tag może służyć do wymuszania pełnego odświeżania, gdy kontrolka w przeciwnym razie wyzwoli częściowe renderowanie.

Przewodnik: wyzwalacze Cross-UpdatePanel

  1. Utwórz nową stronę ASP.NET z ustawionym obiektem ScriptManager w celu włączenia renderowania częściowego. Dodaj do tej strony dwa kontrolki UpdatePanele — w pierwszej kolejności dołącz kontrolkę Etykieta ( Label1 ) i dwa kontrolki Przycisk ( Button1 i Button2 ). Przycisk1 powinien powiedzieć Kliknij, aby zaktualizować zarówno, jak i Przycisk2, powinien powiedzieć Kliknij, aby zaktualizować to lub coś wzdłuż tych wierszy. W drugim UpdatePanel dołącz tylko kontrolkę Etykieta (Label2), ale ustaw jej właściwość ForeColor na inną niż domyślną, aby ją rozróżnić.
  2. Ustaw właściwość UpdateMode obu tagów UpdatePanel na wartość Warunkowe.

Lista 1: Znaczniki dla default.aspx:



<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
   <head runat="server">
      <title>Untitled Page</title>
   </head>
   <body>
      <form id="form1" runat="server">
         <asp:ScriptManager EnablePartialRendering="true"
            ID="ScriptManager1" runat="server"></asp:ScriptManager>
         <div>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server"
               UpdateMode="Conditional">
               <ContentTemplate>
                  <asp:Label ID="Label1" runat="server" />
                  <br />
                  <asp:Button ID="Button1" runat="server"
                     Text="Update Both Panels" OnClick="Button1_Click" />
                  <asp:Button ID="Button2" runat="server"
                     Text="Update This Panel" OnClick="Button2_Click" />
               </ContentTemplate>
            </asp:UpdatePanel>
            <asp:UpdatePanel ID="UpdatePanel2" runat="server"
               UpdateMode="Conditional">
               <ContentTemplate>
                  <asp:Label ID="Label2" runat="server" ForeColor="red" />
               </ContentTemplate>
               <Triggers>
                  <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
               </Triggers>
            </asp:UpdatePanel>
         </div>
      </form>
   </body>
</html>

  1. W procedurze obsługi zdarzeń click dla elementu Button1 ustaw wartość Label1.Text i Label2.Text na coś zależnego od czasu (na przykład DateTime.Now.ToLongTimeString()). W przypadku procedury obsługi zdarzeń click dla elementu Button2 ustaw wartość zależną od czasu tylko Etykieta1.Text.

Lista 2: Codebehind (trimmed) w pliku default.aspx.cs:

public partial class _Default : System.Web.UI.Page
{
    protected void Button1_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToLongTimeString();
        Label2.Text = DateTime.Now.ToLongTimeString();
    }
    protected void Button2_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToLongTimeString();
    }
}
  1. Naciśnij klawisz F5, aby skompilować i uruchomić projekt. Pamiętaj, że po kliknięciu przycisku Aktualizuj oba panele obie etykiety zmieniają tekst; jednak po kliknięciu przycisku Aktualizuj ten panel tylko etykieta1 aktualizuje.

Zrzut ekranu przedstawiający pierwszy przycisk z informacją Aktualizuj zarówno panele, jak i drugi przycisk z informacją Update This Panel (Aktualizuj ten panel).

(Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Pod kapturem

Korzystając z przykładu, który właśnie skonstruowaliśmy, możemy przyjrzeć się temu, co robi ASP.NET AJAX i jak działają nasze wyzwalacze krzyżowe UpdatePanel. W tym celu będziemy pracować z wygenerowanym źródłowym kodem HTML strony, a także rozszerzeniem Mozilla Firefox o nazwie FireBug — z nim możemy łatwo sprawdzić postbacks AJAX. Użyjemy również narzędzia odbicia platformy .NET przez Lutza Roedera. Oba te narzędzia są swobodnie dostępne online i można je znaleźć za pomocą wyszukiwania w Internecie.

Badanie kodu źródłowego strony pokazuje prawie nic z zwykłych; kontrolki UpdatePanel są renderowane jako <div> kontenery i możemy zobaczyć, że zasób skryptu zawiera element <asp:ScriptManager>. Istnieją również kilka nowych wywołań specyficznych dla AJAX do pageRequestManager, które są wewnętrzne w bibliotece skryptów klienta AJAX. Na koniec widzimy dwa kontenery UpdatePanel — jeden z renderowanych przycisków z dwoma <asp:Label> kontrolkami renderowanych <input> jako <span> kontenery. (Jeśli sprawdzisz drzewo DOM w aplikacji FireBug, zauważysz, że etykiety są wygaszone, aby wskazać, że nie generują widocznej zawartości).

Kliknij przycisk Aktualizuj ten panel i zwróć uwagę, że górny element UpdatePanel zostanie zaktualizowany o bieżący czas serwera. W obszarze FireBug wybierz kartę Konsola, aby można było zbadać żądanie. Najpierw sprawdź parametry żądania POST:

Zrzut ekranu przedstawiający okno dialogowe Firebug z wybraną konsolą.

(Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Należy pamiętać, że element UpdatePanel wskazał na kod AJAX po stronie serwera dokładnie, który drzewo sterowania zostało wyzwolone za pośrednictwem parametru ScriptManager1: Button1 kontrolki UpdatePanel1 . Teraz kliknij przycisk Aktualizuj oba panele. Następnie, badając odpowiedź, widzimy rozdzielaną potokiem serię zmiennych ustawionych w ciągu; W szczególności widzimy górny element UpdatePanel, UpdatePanel1, ma cały kod HTML wysłany do przeglądarki. Biblioteka skryptów klienta AJAX zastępuje oryginalną zawartość HTML UpdatePanel nową zawartością za pośrednictwem .innerHTML właściwości, dlatego serwer wysyła zmienioną zawartość z serwera jako HTML.

Teraz kliknij przycisk Aktualizuj oba panele i sprawdź wyniki z serwera. Wyniki są bardzo podobne — oba panele UpdatePanel otrzymują nowy kod HTML z serwera. Podobnie jak w przypadku poprzedniego wywołania zwrotnego, jest wysyłany dodatkowy stan strony.

Jak widać, ponieważ żaden specjalny kod nie jest używany do wykonania zwrotnego kodu AJAX, biblioteka skryptów klienta AJAX jest w stanie przechwytywać postbacki formularzy bez dodatkowego kodu. Kontrolki serwera automatycznie korzystają z języka JavaScript, aby nie przesyłały automatycznie formularza — ASP.NET automatycznie wprowadza kod do sprawdzania poprawności formularza i stanu, głównie osiągany przez automatyczne dołączanie zasobów skryptu, klasę PostBackOptions i klasę ClientScriptManager.

Rozważmy na przykład kontrolkę CheckBox; sprawdź dezasemblacji klas w odbiciach platformy .NET. W tym celu upewnij się, że zestaw System.Web jest otwarty i przejdź do System.Web.UI.WebControls.CheckBox klasy, otwierając metodę RenderInputTag . Poszukaj warunkowego sprawdzania AutoPostBack właściwości:

Zrzut ekranu przedstawiający kod rozpoczynający się od przycisku Kliknij równe.

(Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Gdy automatyczne wycofywanie jest włączone w kontrolce CheckBox (za pośrednictwem właściwości AutoPostBack jest prawdziwe), wynikowy <input> tag jest w związku z tym renderowany za pomocą skryptu obsługi zdarzeń ASP.NET w jego onclick atrybucie. Przechwycenie przesyłania formularza pozwala następnie na wstrzyknięcie ASP.NET AJAX do strony nieintrusywnie, co pomaga uniknąć potencjalnych zmian powodujących niezgodność, które mogą wystąpić przy użyciu ewentualnie nieoczyszczonego zastąpienia ciągu. Ponadto umożliwia to każdej niestandardowej kontroli ASP.NET wykorzystania możliwości ASP.NET AJAX bez dodatkowego kodu do obsługi jego użycia w kontenerze UpdatePanel.

Funkcja <triggers> odpowiada wartościom zainicjowanym w wywołaniu PageRequestManager w celu _updateControls (należy pamiętać, że biblioteka skryptów klienta ASP.NET AJAX wykorzystuje konwencję, że metody, zdarzenia i nazwy pól rozpoczynające się od podkreślenia są oznaczone jako wewnętrzne i nie są przeznaczone do użytku poza samą biblioteką). Dzięki niemu możemy zaobserwować, które kontrolki mają spowodować wycofywanie AJAX.

Na przykład dodajmy dwie dodatkowe kontrolki do strony, pozostawiając jedną kontrolkę poza panelami UpdatePanel i pozostawiając jedną kontrolkę w elemecie UpdatePanel. Dodamy kontrolkę CheckBox w górnej kontrolce UpdatePanel, a lista rozwijana Lista rozwijana z wieloma kolorami zdefiniowanymi na liście. Oto nowy znacznik:

Lista 3: Nowy znacznik

<%@ Page Language="C#" AutoEventWireup="true"
 CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
 <head id="Head1" runat="server">
 <title>Untitled Page</title>
 </head>
 <body>
 <form id="form1" runat="server">
 <asp:ScriptManager EnablePartialRendering="true"
 ID="ScriptManager1" runat="server"></asp:ScriptManager>
 <div>
 <asp:UpdatePanel ID="UpdatePanel1" runat="server"
 UpdateMode="Conditional">
 <ContentTemplate>
 <asp:Label ID="Label1" runat="server" /><br />
 <asp:Button ID="Button1" runat="server"
 Text="Update Both Panels" OnClick="Button1_Click" />
 <asp:Button ID="Button2" runat="server"
 Text="Update This Panel" OnClick="Button2_Click" />
 <asp:CheckBox ID="cbDate" runat="server"
 Text="Include Date" AutoPostBack="false"
 OnCheckedChanged="cbDate_CheckedChanged" />
 </ContentTemplate>
 </asp:UpdatePanel>
 <asp:UpdatePanel ID="UpdatePanel2" runat="server"
 UpdateMode="Conditional">
 <ContentTemplate>
 <asp:Label ID="Label2" runat="server"
 ForeColor="red" />
 </ContentTemplate>
 <Triggers>
 <asp:AsyncPostBackTrigger ControlID="Button1" 
 EventName="Click" />
 <asp:AsyncPostBackTrigger ControlID="ddlColor" 
 EventName="SelectedIndexChanged" />
 </Triggers>
 </asp:UpdatePanel>
 <asp:DropDownList ID="ddlColor" runat="server"
 AutoPostBack="true"
 OnSelectedIndexChanged="ddlColor_SelectedIndexChanged">
 <asp:ListItem Selected="true" Value="Red" />
 <asp:ListItem Value="Blue" />
 <asp:ListItem Value="Green" />
 </asp:DropDownList>
 </div>
 </form>
 </body>
</html>

I oto nowy kod za:

Lista 4: Codebehind

public partial class _Default : System.Web.UI.Page
{
    protected void Button1_Click(object sender, EventArgs e)
    {
        if (cbDate.Checked)
        {
            Label1.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss");
            Label2.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss");
        }
        else
        {
            Label1.Text = DateTime.Now.ToLongTimeString();
            Label2.Text = DateTime.Now.ToLongTimeString();
        }
    }
    protected void Button2_Click(object sender, EventArgs e)
    {
        if (cbDate.Checked)
        {
            Label1.Text = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss");
        }
        else
        {
            Label1.Text = DateTime.Now.ToLongTimeString();
        }
    }
    protected void cbDate_CheckedChanged(object sender, EventArgs e)
    {
        cbDate.Font.Bold = cbDate.Checked;
    }
    protected void ddlColor_SelectedIndexChanged(object sender, EventArgs e)
    {
        Color c = Color.FromName(ddlColor.SelectedValue);
        Label2.ForeColor = c;
    }
}

Chodzi o to, że lista rozwijana wybiera jedną z trzech kolorów, aby pokazać drugą etykietę, że pole wyboru określa, czy jest pogrubiona, i czy etykiety wyświetlają datę, a także godzinę. Pole wyboru nie powinno powodować aktualizacji AJAX, ale lista rozwijana powinna, mimo że nie jest ona umieszczona w elemecie UpdatePanel.

Zrzut ekranu przedstawiający przeglądarkę internetową o nazwie Strona bez tytułu i listę rozwijaną z kolorem Niebieski zaznaczonym poniżej przycisku z napisem Aktualizuj oba panele.

(Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Jak widać na powyższym zrzucie ekranu, ostatni przycisk do kliknięcia był prawym przyciskiem Aktualizuj ten panel, który zaktualizował czas u góry niezależnie od czasu dolnego. Data została również wyłączona między kliknięciami, ponieważ data jest widoczna w dolnej etykiecie. Wreszcie jest kolor etykiety dolnej: został zaktualizowany ostatnio niż tekst etykiety, który pokazuje, że stan kontroli jest ważny, a użytkownicy oczekują, że zostaną zachowane za pośrednictwem poświadczeń AJAX. Jednak czas nie został zaktualizowany. Czas został automatycznie ponownie wypełniony przez trwałość pola __VIEWSTATE strony interpretowanej przez środowisko uruchomieniowe ASP.NET, gdy kontrolka była ponownie renderowana na serwerze. Kod serwera ASP.NET AJAX nie rozpoznaje metod zmiany stanu kontrolek; po prostu ponownie wypełnia stan widoku, a następnie uruchamia zdarzenia, które są odpowiednie.

Należy jednak zwrócić uwagę, że gdybym zainicjował czas w Page_Load przypadku, czas byłby poprawnie zwiększany. W związku z tym deweloperzy powinni być ostrożni, że odpowiedni kod jest uruchamiany podczas odpowiednich procedur obsługi zdarzeń i unikać używania Page_Load, gdy program obsługi zdarzeń kontroli będzie odpowiedni.

Podsumowanie

Kontrolka UpdatePanel rozszerzeń ASP.NET AJAX jest wszechstronna i może korzystać z wielu metod identyfikowania zdarzeń kontroli, które powinny spowodować jego aktualizację. Obsługuje ona automatyczne aktualizowanie przez kontrolki podrzędne, ale może również reagować na zdarzenia sterujące w innym miejscu na stronie.

Aby zmniejszyć potencjał ładowania serwera, zaleca się, aby ChildrenAsTriggers właściwość UpdatePanel była ustawiona na false, i że zdarzenia są domyślnie włączone, a nie uwzględniane domyślnie. Zapobiega to również wszelkim niepotrzebnym zdarzeń powodującym potencjalnie niepożądane skutki, w tym walidację i zmiany pól wejściowych. Te typy usterek mogą być trudne do wyizolowania, ponieważ strona jest aktualizowana w sposób niewidoczny dla użytkownika, a przyczyna może nie być natychmiast oczywista.

Badając wewnętrzne działania modelu po przechwyceniu formularza ASP.NET AJAX, byliśmy w stanie ustalić, że korzysta z platformy już dostarczonej przez ASP.NET. W ten sposób zachowuje maksymalną zgodność z kontrolkami zaprojektowanymi przy użyciu tej samej struktury i intruzuje minimalnie na każdym dodatkowym języku JavaScript napisanym dla strony.

Życiorys

Rob Paveza jest starszym deweloperem aplikacji .NET w firmie Terralever (www.terralever.com), wiodącej firmie zajmującej się marketingiem interaktywnym w firmie Tempe, AZ. Można do niego dotrzeć pod adresem robpaveza@gmail.com, a jego blog znajduje się w http://geekswithblogs.net/robp/lokalizacji .

Scott Cate współpracuje z technologiami internetowymi firmy Microsoft od 1997 roku i jest prezesem myKB.com (www.myKB.com), gdzie specjalizuje się w pisaniu ASP.NET opartych na aplikacjach skoncentrowanych na rozwiązaniach oprogramowania bazy wiedzy. Scott może skontaktować się za pośrednictwem adresu e-mail scott.cate@myKB.com lub jego bloga na ScottCate.com