Poznámka: články jsou již mnoho let staré, doba se posunula, mnoho věcí v nich doporučovaných je již dnes překonané - berte s rezervou!


ASP.NET Ajax a Atlas a obnovování části stránky (Atlas Framework II)

Častým nasazením Ajaxu je obnovení (update) pouze nějaké části stránky. Zatímco serverové prvky ASP.NET umožňují změny ve stránce pouze po postbacku (po něm musí prohlížeč znovu načíst celou stránku), Atlas a jeho komponenta UpdatePanel umožňuje vyznačit ve stránce místo, které se má samostatně obnovovat, a také snadno nadefinovat podmínky, při kterých má k obnovení dojít.

Pokud nemáte ani páru, co je to Ajax nebo Atlas, prosím, začněte nejdříve s mým předchozím článkem na toto téma:
ASP.NET Ajax, Atlas a automatické doplňování výrazu

Obnovení části stránky (partial update) se může hodit v mnoha případech – nějaká část stránky dostává aktuální data zvenčí (například z webové služby), nebo se má daná část měnit po uplynutí nějakého časového intervalu (například když chceme na stránce střídat reklamní bannery) nebo chceme provézt update stránky na základě uživatelovy akce (třeba kliknutí), ale je zbytečné znovu posílat celou stránku, když chceme obnovit jen nějakou malou část. Ukážu návod na všechny 3 kategorie.

Příklad 1. – Hodiny

Předem předesílám, že mít na webu hodiny s aktuálním časem je podle mne zbytečné, ale je to hezký příklad. Pro příklad doporučuji založit novou „Atlas“ Web Site, Visual Studio tak za vás vloží nutné knihovny Atlas Frameworku.

Aspx soubor s hodinovým příkladem může vypadat takto,

Hodiny.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Hodiny.aspx.cs" Inherits="Hodiny" %> <!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"> <div> <atlas:ScriptManager runat="server" ID="ScriptManager1" EnablePartialRendering="true"> </atlas:ScriptManager> <atlas:TimerControl ID="Timer1" Interval="1000" runat="server" OnTick="Timer1_Tick"> </atlas:TimerControl> <atlas:UpdatePanel ID="UpdatePanel1" runat="server" > <ContentTemplate> <asp:Label ID="Label1" runat="server" /> </ContentTemplate> <Triggers> <atlas:ControlEventTrigger ControlID="Timer1" EventName="Tick" /> </Triggers> </atlas:UpdatePanel> </div> </form> </body> </html>

A ještě Code-behind soubor:

Hodiny.aspx.cs:

using System; public partial class Hodiny : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { UpdateTime(); } protected void Timer1_Tick(object sender, EventArgs e) { UpdateTime(); } private void UpdateTime() { Label1.Text = DateTime.Now.ToLongTimeString(); } }

A teď kratičké vysvětlení (protože všechno je tak krásně jednoduché). Komponenta ScriptManager má povolené PartialRendering, jinak by to prostě nešlo. O to, aby se čas neustále obnovoval, se stará komponenta TimerControl. Každou sekundu vyvolává událost Tick – tím se zavolá funkce UpdateTime. Samotný „vnitřek“ UpdatePanelu má dvě části – ContentTemplate, ve které je to, co panel ve výsledku zobrazuje, a Triggers, které obsahují definice událostí, které způsobí obnovení panelu. Triggery jsou dvou druhů – ControlEventTrigger (panel se obnoví, při události některého z ovládacích prvků stránky, ControlID udává, který prvek to je, a EventName která jeho událost způsobí obnovení panelu). Ještě můžete použít ControlValueTrig­ger, který se spustí, pokud se změní hodnota vlastnosti ovládacího prvku.

Můžete zkusit příklad – čas se mění (i když se nemusí podařit provést update každou sekundu), ale zbytek stránky se neobnovuje.

Jen pro pořádek – takovéto hodiny ukazují serverový čas. Pokud se vám zdá, že hodiny nepracují dostatečně svižně (každou vteřinu je potřeba provézt dotaz k serveru a přijmout odpověď) a zároveň by vám stačilo ukazovat klientovi čas, který má on sám nastaven, musíte stránku přepsat jinak.

Myslím, že smysl je jasný – hodiny jsou hloupý příklad ale pokud vyste například každých 20 vteřin chtěli vyměnit reklamní banner, bude tento přístup naprosto dostačující.

Příklad 2. – Načítání z webové služby

Představte si, že chcete na stránce zobrazit informace, které získáte z webové služby a udržovat je aktuální. Například zobrazovat v úzkém proužku nejnovější zprávu ze zpravodajského serveru. Žádnou podobnou službu se mi teď nechce hledat, takže její imitaci napíšu sám. Může vypadat třeba takhle (Vrací stále stejnou zprávu, ale mění se aspoň čas, pro ilustraci to stačí):

News.asmx:

<%@ WebService Language="C#" Class="News" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class News : System.Web.Services.WebService { [WebMethod] public string GetLatest() { return DateTime.Now + " -> Jednání o vládě opět zkrachovala..."; } }

Vlastní stránka News.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="News.aspx.cs" Inherits="News" %> <!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> <script type="text/xml-script"> <page xmlns:script="http://schemas.microsoft.com/xml-script/2005" xmlns:atlas="http://schemas.microsoft.com/atlas/2005"> <components> <timer id="timer1" interval="3000" enabled="true" tick="timer1_tick" /> </components> </page> </script> <script type="text/javascript"> function timer1_tick() { News.GetLatest(OnCallback); } function OnCallback(result) { var label = document.getElementById("Label1"); label.innerHTML = result; } </script> </head> <body> <form id="form1" runat="server"> <div> <atlas:ScriptManager ID="ScriptManager1" runat="server"> <Services> <atlas:ServiceReference Path="News.asmx" /> </Services> </atlas:ScriptManager> <asp:Label ID="Label1" runat="server" Text="Label" /> </div> </form> </body> </html>

Opět komentář: tak především, codebehindový soubor nemusí obsahovat žádný kód. Také není použita komponenta UpdatePanel, protože o nastavení textu v prvku label se stará pouze JavaScript. Také pouze JavaScript volá webovou službu a čeká na její výsledek (funkce OnCallback je zavolána v momentě, kdy je k dispozici výsledek – ten je předán jako parametr result).

Kromě JavaScriptu stránka také obsahuje xml-script s klientskou komponentou Timer (neplést s TimerControl!) – ta také pracuje jako časovač, ale po uplynutí intervalu nevolá serverovou metodu, ale JavaScriptovou funkci timer1_tick přímo na klientovi. Takže při žádném obnovení nedochází k další interakci s www serverem (pouze se serverem, který poskutyje webovou službu).

Příklad 3. – Načítání po uživatelově akci

Posledním příkladem, který mě napadá pro částečné updaty, je jakési uživatelské přepínání. V praxi ho můžete vidět například na nové homepage portálu www.atlas.cz (název portálu a název frameworku, o kterém tu celou dobu vykládám, jsou shodné jen náhodou). Kromě UpdatePanelu k podobné funkci použiju také serverovou ASP.NET komponentu MultiView, která je připravená na toto přepínání, jen ho sama o sobě neumožňuje bez načítání celé stránky. Tam pomůže UpdatePanel.

UserSwitch.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="UserSwitch.aspx.cs" Inherits="UserSwitch" %> <!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"> <atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"> </atlas:ScriptManager> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Přepnout" /> <div style="border: 1px solid black; width: 200px;"> <atlas:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:MultiView ID="MultiView1" runat="server"> <asp:View ID="View1" runat="server"> pohled jedna pohled jedna pohled jedna pohled jedna pohled jedna </asp:View> <asp:View ID="View2" runat="server"> pohled dva pohled dva pohled dva pohled dva pohled dva pohled dva </asp:View> <asp:View ID="View3" runat="server"> pohled tri pohled tri pohled tri pohled tri pohled tri pohled tri </asp:View> <asp:View ID="View4" runat="server"> pohled ctyri pohled ctyri pohled ctyri pohled ctyri pohled ctyri </asp:View> </asp:MultiView> </ContentTemplate> <Triggers> <atlas:ControlEventTrigger ControlID="Button1" EventName="Click" /> </Triggers> </atlas:UpdatePanel> </div> </form> </body> </html>

UserSwitch.aspx.cs

using System; public partial class UserSwitch : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void Button1_Click(object sender, EventArgs e) { MultiView1.ActiveViewIndex = (MultiView1.ActiveViewIndex + 1) % 4; } }

Poslední komentář: většinu práce obstarává control MultiView. Při stisknutí tlačítka se pouze přepne aktivní pohled. Všechny pohledy jsou natvrdo v kódu (vnořené controly View). Ke klientovi se vždy posílají všechna View a ta, která nejsou zobrazena, jsou součástí ViewState.

Solution s příklady ke stažení: PartialUpdates.zip

Perlička na závěr – první dva příklady v Opeře nedělají nic, poslední v Opeře funguje jen tak, že se neobnovuje jen část stránky, ale vždycky celá. V IE a Firefoxu fungují všechny příklady.

Související články: ASP.NET Ajax, Atlas a automatické doplňování výrazu (Atlas Framework I)

Ohodnoťte prosím užitečnost článku




13
 
52
 
29
 
27
 
4
 
 
Vložit komentář:
 

 



 

 

Nepoužívejte žádné html ani texy značky, odřádkování se zachová. Pokud uvádíte zdrojový kód, můžete ho vložit mezi značky
<syntax jazyk="PHP">...</syntax>,
bude potom zformátován. Jako atribut můžete uvést PHP, C#, HTML, CSS a mnoho dalších.


opiste cislo Opište číslo:

 

11. 11. 2006 16:18:31
[1] (MK Zcout (zcout(at)seznam.cz))
Hm... odpovědět
...pěkný stránky.