Áttekintés Alapesetben az ASP.NET-ben az esemény bekövetkezésekor az oldalunk teljesen újratöltődik és nem tárolja el a kliens állapotát automatikusan. Ezért kell foglalkoznunk a Szerver vagy Kliens oldali állapotkezeléssel. Megismerkedünk a ViewState (kliens oldali állapotmentés) illetve a SessionState (szerver oldali állapotmentés) állapotmentésekkel. Adatforrásként használhatunk XML fájlokat, amelyek kezeléséhez a System.IO és System.XML névtereket és az XMLReader osztályt használhatjuk fel. Megismerkedünk a generikus List<> típussal. Eddig még nem használt vezérlőket is megismerünk: PlaceHolder, RadioButtonList. A gyakorlat feladata A következő feladatban egy olyan web alkalmazást készítünk, melyben egy több kérdésből (3 db) álló Teszt-et kell kitölteni. A teszt kitöltése közben és után megjelenítjük a kitöltés eredményét. 1. ábra Forma I-es teszt első kérdése Probléma Tervezés Szükségünk van arra, hogy két szerverhez történő kapcsolódás között a már beolvasott kérdések ne vesszenek el. Ezeket szerver oldalon mentjük el a Session tulajdonság segítségével, melyben a Session változók értékét tárolhatjuk. Így tároljuk azt is, hogy melyik kérdés következik. Az oldalon a versenyző megadhatja a nevét. Ezt az információt is őrizzük meg. Nem szükséges, hogy a szerveren tároljuk elegendő a kliens gépen eltárolnunk a ViewState-el, ezért a TextBox vezérlő EnableViewState tulajdonsága a felelős. A jó válaszok számát tartalmazó TaxtBox-al is hasonlóképpen járjunk el.
Nézzük meg, hogyan működik majd a kérdező (kérdéseket generáló) oldalunk. Az oldal Page_Init eseményében hozzuk létre és helyezzük el az oldalon a kérdés szövegét megjelenítő Label-t illetve a válaszlehetőségeket megjelenítő RadioButtonList vezérlőt dinamikusan. Az oldal Page_Load eseményében kiolvassuk a Session változóból a kérdések listáját és az aktuális kérdés számát. Amennyiben először töltődik be az oldal (nem ispostback) a dinamikusan létrehozott vezérlőkben elhelyezzük a kérdés szövegét (a kérdés sorszámával együtt) és a lehetséges válaszokat. Megjelenítjük továbbá az eddigi helyes válaszok számát. Ennek a vezérlőnek is őrizzük meg az állapotát (kliens oldalon). Helyezzünk el az oldalon egy Button-t is. Segítségével a megjelölt választ elküldjük a szervernek. A szerveren ellenőrizzük a válasz helyességét és megjelenítjük a következő kérdést és a hozzá tartozó lehetséges válaszokat. Ne feledkezzünk meg arról, hogy a válasz kiválasztása után a gombnyomás hatására újratöltődik az oldal. Fontos, hogy a RadioButtonList megtartsa az állapotát (ezért helyezzük el a Page_Init eseményben), így tudjuk leellenőrizni a válasz helyességét a nyomógomb click eseményéhez rendelt eseménykezelő függvényben, mely a Page_load esemény bekövetkezése után kerül végre hajtásra (ezért ellenőrizzük a PostBack tulajdonságot is). Megvalósítás Készítsünk egy új ASP.NET Web Site-ot. Először készítsük el az XML fájlt (kerdesek.xml), amiben a kérdéseket tároljuk. Adjunk a solution-höz egy üres XML fájlt. 2. ábra XML fájl hozzádas Hozzuk létre ebben a megfelelő Node-okat. A válaszlehetőségek Node-jában adjuk meg attribútum segítségével, hogy melyik válasz a helyes.
<Teszt> <Kerdes > <Kerdessz>Mikor született vettel?</kerdessz> <Valasz jo="true">xx. század</valasz> <Valasz >XIX. század</valasz> <Valasz >XXI. század</valasz> <Valasz >XVIII. század</valasz> </Kerdes> <Kerdes >... </Kerdes> <Kerdes >... </Kerdes> </Teszt> Egy kérdés egy osztály legyen, melynek mezői: maga a kérdés szövege, a válaszok listája és a jó válasz sorszáma. Hozzuk létre ezt a C# Class-t az App_Code mappában. Ezen kérdésekből fogunk egy listát létrehozni, melybe majd az XML fájlból olvassuk be a kérdéseket. Szabjuk testre a főoldalunkat (Default.aspx). Helyezzünk el az oldalon egy Button-t (nyomógombot). Írjuk meg a code-behind oldalon, hogy ha rákattintunk a nyomógombra, akkor kiolvassuk a kérdéseket az XML fájlból egy listába majd átirányítjuk a felhasználót egy másik oldalra, ahol megjelenik az első kérdés. Ehhez az oldal Page_Load eseményében ellenőrizzük az IsPostBack tulajdonság segítségével, hogy PostBack-ről van-e szó. Amennyiben igen: hozzunk létre egy listát, melynek elemei a korábban létrehozott Kerdes osztály: List<Kerdes> lista = new List<Kerdes>(); olvassuk be az XML fájlból a kérdéseket és adjuk az elkészített listához (érdemes kivételkezelést használni). XmlReader xmlr = XmlReader.Create(Server.MapPath("~") + "/kerdesek.xml"); XMLReader fontosabb metódusai MoveToContent Read IsStartElement ReadStartElement ReadElementString leírás Content Node-ra való ugrás Következő Node olvasása Kezdőelem-e? Kezdőelem olvasása Node tartalmának beolvasása
HasAttributes GetAttributes ReadEndElement Close van attribútuma az aktuális elemnek az aktuális elem index-edik attribútuma aktuális elem záró Node tulajdonságának ellenőrzésre majd ugrás a következő node-ra a fájl bezárása mentsük el Session változóban a kérdések listáját és adjuk meg, hogy az első kérdés következik. Session["kerdesek"] = lista; Session["kerdesSzam"] = 1; Irányítsuk át a kérést a teszteltető oldalra (kerdez.aspx) Hozzuk létre ezt az oldalt is a master page alapján (kerdez.aspx). Ahogy korábban megnéztük szükségünk lesz az oldalon két Label-re ezekben jelenítjük meg, hogy hányadik kérdésnél járunk és hogy eddig hány jó választ adtunk. Helyezzünk el az oldalon a játékos nevének megadásához egy TextBox-ot. Az előbb létrehozott vezérlők EnableViewState tulajdonságát állítsuk True (igaz) ra, hogy az egyes kérések között megőrizzék az állapotukat. 3. ábra A ViewState beállítása Adjunk továbbá az oldalhoz egy Button-t. Text tulajdonságát inicializáljuk az OK szöveggel. Szükségünk van még egy PlaceHolder-re, mellyel a dinamikusan futási időben megjelenített vezérlőket kezeljük. 4. ábra PlaceHolder használata
Készítsük el a kerdez.aspx oldalhoz tartozó code-behind fájlban az oldalhoz tartozó kódot. A következő típusú változókra van szükségünk: RadioButtonList a lehetséges válaszok megjelenítéséhez, Label a kérdés szövegének megjelenítéséhez, int az aktuális kérdés számához, List<Kerdes> a kérdések listája RadioButtonList rdbl; Label kerdessz; int kerddb; List<Kerdes> lista; A Page_Init eseményben létrehozzuk a RadioButton és a Label egy példányát. Majd hozzáadjuk a PlaceHolder-hez. A Page_Load eseményben lekérdezzük a Session asszociatív tömbből a kérdésekből képzett listát és azt, hogy melyik kérdésnél tartunk. Amennyiben az oldalt először jelenítjük meg meghívjuk a kérdések megjelenítésére létrehozott függvényt. FONTOS! A Session változó értékének lekérdezésénél ne felejtsünk el típus kényszerítést végezni (cast). A kérdést generáló függvényben megjelenítjük az aktuális kérdés sorszámát. A listából kiválasztjuk a hozzá tartozó kérdés szövegét és a lehetséges válaszokat. Hozzáadjuk őket a RadioButtonList-hez. Végül az első lehetséges választ kijelöljük. Erre azért van szükség, mert ha a felhasználó nem jelöl be választ és úgy küldi el a szervernek feldolgozásra az eredményt, akkor az az oldal nem megfelelő működéséhez vezet. public void kerdgeneral() { KerdSzam.Text = Convert.ToString(kerdDB) + ". kérdés"; Kerdes k = lista.elementat(kerddb - 1); kerdessz.text = k.szoveg; //megjelenítjük az aktuális kérdést int i = 1; //megjelenítjük a válaszokat foreach (string kerd in k.valaszok) rdbl.items.add(new ListItem(kerd, Convert.ToString(i++))); rdbl.selectedindex = 0; }
A kérdésre adott választ a nyomógomb click eseményéhez rendelt eseménykezelő függvényben dolgozzuk föl. Először leellenőrizzük, hogy a válasz helyes-e. Megnézzük, hogy a RadioButtonList vezérlőnek melyik indexű eleme lett kiválasztva. Ezt összehasonlítjuk az aktuális kérdés objektum jó mezőjének értékével. Ha jó volt a válaszadás, akkor a megfelelő Label vezérlő Text tulajdonságában növeljük az aktuális értéket. Miután leellenőriztük a megoldást növeljük a kérdés számot. El is mentjük az állapotát. Kerdes k = lista.elementat(kerddb - 1); if (rdbl.selecteditem.value.equals(convert.tostring(k.jo))) jovalaszdb.text = Convert.ToString(Convert.ToInt16(joValaszDb.Text) + 1); Session["kerdesSzam"] = ++kerddb; Amennyiben van még további kérdés megjelenítjük. Ha nincs több kérdés, akkor egy eredmeny.aspx oldalra továbbítjuk a felhasználót, ahol megjelenítjük az eredményét. FONTOS! Ne felejtsük el, hogy a nyomógomb click eseményéhez rendelt eseménykezelő függvénynek a végrehajtása előtt lefut a Page_Init és Page_Load esemény is. Ezért a RadioButtonList elemeit nem szabad a válasz helyességének ellenőrzése előtt törölni. Ezért fut le a Page_Load eseményben a kérdés generálás függvény csak egyszer. Már csak az eredmény megjelenítéséhez kell elkészítenünk az eredmeny.aspx oldalt. Az oldalhoz adjunk két Label vezérlőt. Az egyikben a helyes válaszok számát adjuk meg a másikban azt, hogy összesen hány kérdés volt. Az oldalhoz tartozó code-behind fájlban írjuk meg, hogy az oldal betöltődésekor jelenjenek meg a megfelelő értékek. 5. ábra A teszt eredménye