Cursus ASP.net 1

283
Contents 1 ASP.net : Beginnen met ASP.net..................................2 1.1 Inleiding................................................... 2 1.2 Statische webpagina's.......................................2 Wat is een statische webpagina ?................................2 Hoe worden statische webpagina's aangeboden?....................2 1.3 Dynamische webpagina's......................................3 Client-side dynamische webpagina's..............................3 Server-side dynamische webpagina's..............................4 1.4 ASP.net installeren......................................... 5 1.5 ASP.net testen.............................................. 5 Test met een eenvoudige tektverwerker...........................5 Test met Visual Studio.Net......................................6 2 ASP.net : ASP.net in vogelvlucht................................8 2.1 Wat is .net................................................. 8 2.2 Common Language Runtime (CLR)...............................8 2.3 Objecten en klassen......................................... 8 2.4 .Net Basisklassen........................................... 9 2.5 Streefdoelen van ASP.net....................................9 Onafhankelijk werken van script-interpreters....................9 De hoeveelheid code verminderen om webapplicaties te bouwen.....9 ASP.net staat toe dat gebruikers bestaande functionaliteit uitbreiden / vervangen..........................................9 Taal is irrelevant (bijna)......................................9 Geen tools nodig...............................................10 2.6 ASP.net code schrijven.....................................10 VS 2005........................................................10 <SCRIPT>-BLOKKEN...............................................10 Inline codeblokken.............................................11 CodeBehind.....................................................12 3 ASP.net : Formulieren..........................................14 3.1 Inleiding.................................................. 14 1 Frank Horemans

description

Course into ASP.NET Webforms in dutch

Transcript of Cursus ASP.net 1

Page 1: Cursus ASP.net 1

Contents

1 ASP.net : Beginnen met ASP.net.....................................................................................................2

1.1 Inleiding..................................................................................................................................2

1.2 Statische webpagina's............................................................................................................2

Wat is een statische webpagina ?...................................................................................................2

Hoe worden statische webpagina's aangeboden?.........................................................................2

1.3 Dynamische webpagina's.......................................................................................................3

Client-side dynamische webpagina's..............................................................................................3

Server-side dynamische webpagina's.............................................................................................4

1.4 ASP.net installeren.................................................................................................................5

1.5 ASP.net testen........................................................................................................................5

Test met een eenvoudige tektverwerker.......................................................................................5

Test met Visual Studio.Net.............................................................................................................6

2 ASP.net : ASP.net in vogelvlucht.....................................................................................................8

2.1 Wat is .net..............................................................................................................................8

2.2 Common Language Runtime (CLR).........................................................................................8

2.3 Objecten en klassen................................................................................................................8

2.4 .Net Basisklassen....................................................................................................................9

2.5 Streefdoelen van ASP.net.......................................................................................................9

Onafhankelijk werken van script-interpreters................................................................................9

De hoeveelheid code verminderen om webapplicaties te bouwen...............................................9

ASP.net staat toe dat gebruikers bestaande functionaliteit uitbreiden / vervangen......................9

Taal is irrelevant (bijna)..................................................................................................................9

Geen tools nodig..........................................................................................................................10

2.6 ASP.net code schrijven.........................................................................................................10

VS 2005.........................................................................................................................................10

<SCRIPT>-BLOKKEN......................................................................................................................10

Inline codeblokken.......................................................................................................................11

CodeBehind..................................................................................................................................12

3 ASP.net : Formulieren...................................................................................................................14

3.1 Inleiding................................................................................................................................14

3.2 Het http protocol..................................................................................................................14

3.3 Html formulieren..................................................................................................................16

De methode GET..........................................................................................................................16

1 Frank Horemans

Page 2: Cursus ASP.net 1

De methode POST........................................................................................................................18

GET of POST..................................................................................................................................19

HTML formulierelementen...........................................................................................................19

Uitgebreid voorbeeld...................................................................................................................20

4 ASP.net : HTML Server-controls....................................................................................................24

4.1 Wat zijn HTML-servercontrols ?...........................................................................................24

4.2 Een gewoon HTML-formulier................................................................................................24

4.3 Een ASP.net serverformulier.................................................................................................25

4.4 __VIEWSTATE.......................................................................................................................25

4.5 Actie ondernemen................................................................................................................27

4.6 Achtergrond..........................................................................................................................27

4.7 Viewstate aangeven.............................................................................................................28

4.8 Html Servercontrols en stijlen..............................................................................................28

4.9 Reageren op events..............................................................................................................29

Serverclick....................................................................................................................................29

Serverchange................................................................................................................................30

5 ASP.net : Web Controls................................................................................................................32

5.1 Wat zijn Web Controls ?.......................................................................................................32

5.2 Visual Studio.net 2005 en Web Controls..............................................................................32

Toepassing....................................................................................................................................32

CodeBehind..................................................................................................................................33

5.3 Elementaire ASP.net Web Form Controls.............................................................................33

5.4 AutoPostBack.......................................................................................................................36

5.5 Input Validation Controls......................................................................................................38

Overzicht......................................................................................................................................38

Achtergrond.................................................................................................................................39

Input Validation Controls Gebruiken............................................................................................40

Validatie controleren....................................................................................................................41

Validatie uitschakelen...................................................................................................................41

5.6 List Controls..........................................................................................................................41

Overzicht......................................................................................................................................41

Achtergrond.................................................................................................................................42

Gebruik.........................................................................................................................................42

5.7 Oefeningen...........................................................................................................................43

6 ASP.net : ASP.net pagina's in detail..............................................................................................46

6.1 Inleiding................................................................................................................................46

2 Frank Horemans

Page 3: Cursus ASP.net 1

6.2 Een ASP.Net pagina uitvoeren..............................................................................................46

Compilatie....................................................................................................................................46

6.3 System.Web.UI.Page: overzicht............................................................................................46

ASP.net pagina's uitvoeren...........................................................................................................46

Events bij het uitvoeren van ASP.net pagina's..............................................................................46

6.4 De eigenschap Request.........................................................................................................48

6.5 De eigenschap Response......................................................................................................49

6.6 De eigenschap IsPostBack.....................................................................................................49

6.7 De eigenschap Context.........................................................................................................51

6.8 De eigenschap Server...........................................................................................................56

6.9 Page Directives.....................................................................................................................59

7 ASP.net : pagina compositie.........................................................................................................61

7.1 Inleiding................................................................................................................................61

7.2 Masterpages.........................................................................................................................61

Een masterpage maken................................................................................................................61

Een inhoudspagina maken............................................................................................................62

Titel instellen................................................................................................................................63

Masterpages nesten.....................................................................................................................63

7.3 Themes.................................................................................................................................63

Inleiding........................................................................................................................................63

Wat is een theme.........................................................................................................................64

Structuur van een theme..............................................................................................................64

Een theme maken.........................................................................................................................65

Themes dynamisch laden.............................................................................................................66

7.4 Wizards.................................................................................................................................67

Wat is een Wizard?.......................................................................................................................67

Structuur van een Wizard.............................................................................................................68

Een Wizard aanmaken..................................................................................................................68

8 ASP.net : User Controls.................................................................................................................73

8.1 User Controls........................................................................................................................73

Wat zijn User Controls..................................................................................................................73

User Controls aanmaken: Kalender.ascx......................................................................................73

Eigenschappen definiëren - Inloggen.ascx....................................................................................76

8.2 Custom Controls...................................................................................................................79

Custom Controls...........................................................................................................................79

8.3 Composite Controls..............................................................................................................88

3 Frank Horemans

Page 4: Cursus ASP.net 1

Wat zijn Composite Controls........................................................................................................88

Een Composite Control maken.....................................................................................................88

8.4 Oefeningen...........................................................................................................................91

9 ASP.net : Dynamische Controls.....................................................................................................92

9.1 Wat zijn Dynamische Controls ?...........................................................................................92

9.2 Dynamische Controls maken: OnInit....................................................................................92

9.3 Event Handlers bij dynamische controls...............................................................................94

9.4 User Controls dynamisch laden............................................................................................96

9.5 Oefeningen...........................................................................................................................98

10 ASP.net : Data binding en List controls.....................................................................................99

10.1 Inleiding................................................................................................................................99

10.2 Data Binding Syntax..............................................................................................................99

10.3 Single Value data binding.....................................................................................................99

10.4 Repeated-Value data-binding: basisprincipes.....................................................................101

10.5 Eenvoudige repeated-value data-binding: DropDownList, ListBox.....................................102

10.6 Repeater - Container.DataItem - Eval.................................................................................108

Attributen voor Object Data Sources......................................................................................114

11 DataList..................................................................................................................................116

11.1 DataList: basisbegrippen.....................................................................................................116

11.2 DataList: Items Selecteren en deselecteren........................................................................118

11.3 ODS hergebruiken met Masterpages..................................................................................122

11.4 DataList: gegevens editeren...............................................................................................124

11.5 DataList: items toevoegen..................................................................................................131

11.6 DataList: items verwijderen................................................................................................133

12 GridView - DetailsView...........................................................................................................135

12.1 GridView: voorbereiding voor 3-tier toepassing.................................................................135

12.2 Gridview: gegevens tonen..................................................................................................139

12.3 GridView: kolommen definiëren.........................................................................................152

12.4 GridView: kolommen sorteren...........................................................................................155

12.5 GridView: pagineren...........................................................................................................160

12.6 GridView: Data editeren.....................................................................................................167

Foutafhandeling.........................................................................................................................172

12.7 GridView - records verwijderen..........................................................................................174

12.8 GridView - rijen selecteren.................................................................................................177

12.9 GridView: gegevens uit een rij tonen..................................................................................177

GridView: rijen aanpassen..........................................................................................................179

4 Frank Horemans

Page 5: Cursus ASP.net 1

DetailsView - gegevens bekijken................................................................................................179

DetailsView - gegevens toevoegen.............................................................................................182

DetailsView - gegevens editeren en verwijderen.......................................................................183

13 geavanceerde databinding.....................................................................................................185

13.1 DataList: dynamische inhoud met ItemDataBound............................................................185

13.2 DataList - eigen format functie...........................................................................................185

14 Databases...............................................................................................................................187

14.1 Inleiding..............................................................................................................................187

14.2 Connectiestring...................................................................................................................187

14.3 Gegevens ophalen: SqlDataAdapter en DataSet.................................................................187

14.4 Gegevens ophalen: SqlCommand en SqlDataReader..........................................................189

14.5 Select instructie met parameters.......................................................................................189

14.6 Gegevens toevoegen: Insert...............................................................................................191

14.7 Gegevens bewerken: Update.............................................................................................194

14.8 Gegevens verwijderen: Delete............................................................................................203

14.9 Gegevens sorteren..............................................................................................................204

14.10 Stored Procedures gebruiken.........................................................................................208

15 Business objecten...................................................................................................................212

15.1 Inleiding..............................................................................................................................212

15.2 2-Tier applicatie..................................................................................................................212

15.3 3-Tier..................................................................................................................................216

16 Web Services..........................................................................................................................220

16.1 Wat zijn Web Services ?......................................................................................................220

16.2 Basisbegrippen...................................................................................................................220

16.3 Een Web Service maken: Publishing...................................................................................220

16.4 Werking van de Web Service..............................................................................................222

16.5 Een Webservice gebruiken: Consuming..............................................................................223

16.6 Werken met verschillende datatypes.................................................................................228

16.7 Toepassing..........................................................................................................................233

5 Frank Horemans

Page 6: Cursus ASP.net 1

1 ASP.NET : BEGINNEN MET ASP.NET

1.1 Inleiding

ASP.net is een nieuwe, krachtige technologie voor het creëren van dynamische webpagina's. Het vormt een bundeling van twee technologieën : Active Server Pages (ASP) en .net.

Je hoeft in principe geen ASP te kennen om te starten met ASP.net, een basiskennis HTML is voldoende om van start te kunnen gaan. Met ASP.net kan je websites maken in de voor jou meest geschikte taal : VB.net, Jscript, C#, of een combinatie van deze talen. In deze cursus zullen we C# als basistaal gebruiken, ik ga er ook van uit dat je reeds over een basiskennis C# beschikt vooraleer deze cursus te volgen.

ASP.net stelt je in staat binnen je toepassing aangepaste pagina's voor verschillende gebruikers te maken, gebruikers te 'volgen' doorheen de website, informatie in een database of XML-bestand op te slaan.

1.2 Statische webpagina's

Wat is een statische webpagina ?

Een statische webpagina is een pagina waarvan de auteur de exacte inhoud en lay-out op voorhand heeft vastgelegd. De pagina is bij elk bezoek en voor elke gebruiker onveranderlijk. Om een statische webpagina te maken gebruik je een teksteditor en sla je het bestand op met een extensie .htm of .html.

Voorbeeld :

<html><head>

<title>Statische webpagina</title></head>

<body><h2>Welkom</h2>Deze pagina is een voorbeeld van een <b>statische</b> webpagina.</body></html>

Om het even wanneer een client deze pagina bezoekt, ze zal er steeds hetzelfde uitzien. De inhoud van de pagina was al bepaald voor het request van de client werd gemaakt.

Hoe worden statische webpagina's aangeboden?

1. Een webauteur schrijft een page in pure HTML en slaat deze op als HTML-bestand op de server.

2. Een gebruiker voert een request naar deze pagina uit 3. De server localiseert het HTML-bestand en biedt deze aan als HTML-stream 4. De server stuurt de HTML-stream over het netwerk naar de browser 5. De browser verwerkt de HTML en toont de pagina.

6 Frank Horemans

Page 7: Cursus ASP.net 1

Statische pagina's zijn gelimiteerd doordat alle inhoud al vooraf in de pagina aanwezig is. In een HTML-pagina kan je bijvoorbeeld de huidige tijd niet weergeven, doordat je als auteur niet op voorhand weet wanneer de gebruiker de pagina zal opvragen.

1.3 Dynamische webpagina's

Er zijn twee manieren om dynamische webpagina's te creëren: client-side en server-side dynamische webpagina's.

Client-side dynamische webpagina's

Bij deze pagina's worden naast HTML-instructies ook instructies naar de browser gestuurd waarmee de browser de pagina interactief kan aanpassen. Deze meegestuurde instructies moeten door de browser wel ondersteund en dus begrepen worden. Javascript en VBscript zijn twee voorbeelden van talen die voor client-side scripting worden gebruikt.

1. Een webauteur maakt een HTML-file. Hij schrijft ook instructies in een andere taal. Deze instructies kunnen in de HTML-code vervat zijn of in aparte bestanden zijn opgeslagen.

2. Een gebruiker voert een request naar deze pagina uit 3. De server localiseert het HTML-bestand en eventueel andere instructie-bestanden 4. De server stuurt dit alles naar de client 5. De browser verwerkt zowel de HTML als de andere instructies (vb. Javascript )

Voorbeeldtechnologieën:

Javascript : dit is de originele browser-scripttaal. Het ontstond door een samenwerking met Sun -de makers van Java- en Netscape, die een scripttaal met de naam Livescript hadden ontwikkeld. Javascript is gemakkelijker te leren dan Java. Het werd beïnvloed door de taal Java, die op zijn beurt ideeën heeft gehaald bij de programmeertaal C.Javascript heeft een ander doel dan de programmeertalen Java en C : ontwerpen van kleine, interactieve toepassingetjes in een browser. Microsoft ontwikkelde ook zijn eigen versie van deze scripttaal onder de naam Jscript.

VBScript: In Internet Explorer 3.0 introduceerde Microsoft hun eigen scripttaal VBscript, afgeleid van de programmeertaal Visual Basic. Het was de bedoeling hiermee de strijd aan te gaan tegen Javascript. VBscript is echter enkel bruikbaar met Internet Explorer en bijgevolg ligt de keuze bij client side scriptig voor het Internet voor de hand : Javascript.

ActiveX Controls: een alleenstaand stukje programmacode geschreven in een taal als C++ of Visual Basic. Het op zichzelf staand programma kan in een webpagina ingebed worden met de OBJECT - tag. Hier hebben we weer te maken met een technologie oorspronkelijk ontwikkeld door Microsoft en dus niet door alle browsers ondersteund.ActiveX-componenten kunnen ook meer functionaliteiten uitvoeren dan VBscript of Javascript, zoals manipulatie van het register of van bestanden op de machine van de gebruiker. Vandaar dat ze vaak geweerd worden om beveiligingsredenen.

Java-Applets : Java is een platformonafhankelijke programmeertaal. Het principe van een Java-applet is het maken van een bestand dat door een Java Virtual Machine op de clientcomputer kan uitgevoerd worden. Java-applets worden standaard met een OBJECT of ook wel met de APPLET-tag ingevoegd in een webpagina.

Curl: een nieuwere ontwikkeling op client-side gebied is Curl. Ook hiervoor moet eerst een Curl-plugin worden geïnstalleerd voor de browser de bestanden kan uitvoeren. Meer op www.curl.com

7 Frank Horemans

Page 8: Cursus ASP.net 1

Server-side dynamische webpagina's

Deze keer schrijft de webauteur instructies hoe de server de HTML-output moet genereren. De server zal de instructies in de gevraagde webpagina dus eerst zelf moeten uitvoeren en daarna het bekomen resultaat naar de browser sturen.

1. Een webauteur schrijft instructies hoe de HTML moet worden gegenereerd 2. Een gebruiker doet een request voor de pagina via zijn browser 3. De server localiseert het bestand met de instructies 4. De server volgt de instructies om HTML te genereren 5. De server stuurt de pas gegenereerde HTML als output naar de browser 6. De browser verwerkt de HTML en toont de pagina

Het verschil is hier dat het verwerken van de instructies gebeurt op de server, vooraleer de pagina naar de gebruiker wordt gestuurd.

Dit betekent dat de programma-instructies verwerkt worden op de server en dat we er (zoals bij client-side scripting) niet over hoeven te waken dat de browser de instructies zal begrijpen.

Zoals je wellicht reeds veronderstelt, volgt ASP.NET dit laatste systeem.

Voorbeeldtechnologieën:

CGI : Common gateway interface is een manier om scripts op een server te plaatsen die gebruikt worden om dynamische webtoepassingen te maken. CGI wordt onder de vorm van een module aan een webserver gekoppeld. Het bestaat al heel wat langer dan ASP en nog steeds gebruiken vele websites deze technologie. Dergelijke scripts worden ontwikkeld in programmeertalen als C, C++ en Perl.

ASP : Active Server Pages wordt nu benoemd als klassieke ASP. In ASP werd een scripttaal gebruikt om dynamische webpagina's te maken. VBscript werd hierbij meest gebruikt, maar ook Javascript (of zelfs Perlscript) behoorden tot de mogelijkheden. ASP is een module (asp.dll) die je koppelt met de webserver, deze module verwerkt de scriptinstructies op de ASP-pagina's op de webserver en retourneert HTML naar de browser.Nadelen hierbij zijn het gebruik van scripttalen die eigenlijk slechts afgeslankte versies zijn van de basistalen waarbij je dus minder mogelijkheden hebt en vooral het feit dat je scriptfragmenten gemixed tussen de HTML instructies staan wat nogal vaak aanleiding geeft tot 'spaghetticode'. De performantie kon hierdoor behoorlijk laag zijn. Een ander nadeel ligt bij de ondersteuning door de webserver, waarbij IIS eigenlijk de enige server is de ASP ten volle ondersteunt.

JSP: Java Serverpages is een technologie die je toestaat HTML ( of XML) elementen te combineren met Javacode. JSP werd geïmplementeerd door verschillende webservers. JSP is heel krachtig en performanter dan ASP. Meer hierover op bij Sun

Coldfusion: Coldfusion is een module die geïnstalleerd dient te worden op de websserver. Coldfusion gebruikt een speciale set tags die geïnterpreteerd worden door de Coldfusion Server Software.

PHP: vroeger Personal Home Pages maar omgedoopt tot PHP Hypertext Preprocessor is een andere scripttaal om dynamische webpagina's te maken. Wanneer een bezoeker een PHP-pagina opvraagt verwerkt de server de PHP instructies en stuurt het resultaat naar de browser.PHP is open-source en platformonafhankelijk. De PHP-syntax is te vergelijken met C en Perl. Vandaar dat dit voor vele ontwikkelaars een hoge drempel vormt.

ASP.NET: ASP.NET is afhankelijk van een module die moet zijn geïnstalleerd op de server. Deze module (aspnet_isapi.dll) doet niet alle werk en geeft een aantal taken

8 Frank Horemans

Page 9: Cursus ASP.net 1

door aan het .NET Framework. We gaan er hier niet te uitgebreid op in, daar de rest van de cursus over ASP.NET handelt.

1.4 ASP.net installeren

Voor het maken van ASP.net toepassingen is volgende software nodig:

Windows 2000 / 2000 server / XP / 2003 server Met Visual Studio 2003/2005/2008/2010: Internet Information Server (IIS) versie 5 /

5.1/6 of hoger. Controleer of dit geïnstalleerd is via Configuratiescherm > Software > Windows

onderdelen...Je kan IIS beheren via het Configuratiescherm > Systeembeheer ... of via Start > uitvoeren > inetmgr.exe

Visual Studio of Visual Web Developer Express: een webserver is meegeleverd, zodat je niet noodzakelijk over IIS hoeft te beschikken.

MDAC: een recente versie van Microsoft Data Access Components, te verkrijgen via www.microsoft.com/data.

het .NET Framework: Win 2000/XP gebruikers installeren het .NET framework, te verkrijgen via: www.microsoft.com/downloads (zoek op .net framework)

1.5 ASP.net testen

Test met een eenvoudige tektverwerker

Voor het maken van ASP.net toepassingen kan je gebruik maken van een eenvoudige tekstverwerker (zoals kladblok) maar bestaan er ook heel wat geavanceerde editoren:

Webmatrix : gratis editor van Microsoft Visual Web Developer 2005 Express : gratis editor van Microsoft met ondersteuning

voor ASP.net 2.0 Visual Studio.net : geïntegreerde ontwikkelomgeving van Microsoft voor het

ontwerpen binnen het .net-framework. Dit wordt de standaard-editor voor deze cursus. ...

Wanneer je beschikt over voldoende rechten om IIS te configureren, dan maak je een virtuele map CursusASPNET aan die wijst naar de map die je voor de cursusvoorbeelden wenst te gebruiken. In deze map heb ik een submap aangemaakt met de naam h1 (hoofdstuk 1).

In deze map plaats ik het bestand tijd1.aspx, gemaakt met kladblok (je kan deze test gerust ook uitvoeren met Visual Studio.net):

<html><head>

<title>Webservertijd</title></head><body><h1>Welkom</h1>In webserverland is het nu :<%= System.DateTime.Now.ToString() %></body></html>

9 Frank Horemans

Page 10: Cursus ASP.net 1

Test met Visual Studio.Net

Hetzelfde voorbeeld kan je maken in Visual Studio.Net:

Kies voor een nieuwe Web Site, location: file system, language: Visual C# Kies een locatie ...\ASPNET20\Beginnen

VS 2003: Kies als locatie http://localhost/h1/tijdVS1

Merk op dat de standaardlocatie voor webbestanden de map c:\inetpub\wwwroot is, je zal daar de webbestanden terugvinden die je maakt met VS.net. Je kan natuurlijk via IIS de locatie van de standaardmap aanpassen.

Zorg voor source-weergave (niet in design) Doe volgende aanpassingen in de code:

<%@ 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"> <div> <h1>Welkom</h1> In webserverland is het nu <%= System.DateTime.Now.ToString() %> </div> </form></body></html>

10

Frank Horemans

Page 11: Cursus ASP.net 1

Voer het project uit.

Hierbij wens ik op te merken dat de manier waarop hier geprogrammeerd wordt niet overeenstemt met de filosofie van Visual Studio.Net, we liggen hier voorlopig niet van wakker.

Merk ook op dat Visual Studio.Net in de map 'Beginnen' aantal bestanden heeft geplaatst, de functie ervan zal in de loop van de lessenreeks aan bod komen.

11

Frank Horemans

Page 12: Cursus ASP.net 1

2 ASP.NET : ASP.NET IN VOGELVLUCHT

1. Wat is .net 2. Common Language Runtime (CLR) 3. Objecten en klassen 4. .Net basisklassen 5. Streefdoelen van ASP.net 6. ASP.net code schrijven

2.1 Wat is .net

ASP.NET maakt deel uit van het .NET Framework. Om inzicht te krijgen in het .NET Framework volgt een overzicht van de voornaamste aspecten :

Een platform ontworpen voor het maken van internet-gerelateerde toepassingen dat technologieën zoals XML,http en SOAP ondersteunt

Een platform dat een aantal uitgebreide en krachtige technieken zoals Windows Forms (gebruikt om GUI : Graphical User Interface toepassingen) en ASP.NET (internet toepassingen) gebruikt.

Een platform met een enorm uitgebreide klassenbibliotheek die verregaande ondersteuning biedt voor data access (relationele database, XML)

Een platform met een basisklassenbibliotheek die honderden classes bevat voor het uitvoeren van bestandsmanipulaties, toegang tot het register, beveiliging, threading,…

Een platform waarbij met verschillende programmeertalen kan worden gewerkt Een platform met een onafhankelijke code uitvoeringseenheid: de Common Language

Runtime (CLR). Deze vormt een onafhankelijke laag boven het besturingssysteem zodat .NET toepassingen op verschillende besturingssystemen kunnen uitgevoerd worden

2.2 Common Language Runtime (CLR)

De Common Language Runtime wordt gebruikt als motor voor alle .NET toepassingen. De rol van de CLR kan je vergelijken met de JVM van Java. De CLR is verantwoordelijk voor het uitvoeren van de code ontwikkeld in .NET applicaties. .NET compilers leveren Intermediate language (IL) i.p.v. machinecode, deze code wordt dan just-in-time (JIT) door de CLR omgezet in machinecodeinstructies.

2.3 Objecten en klassen

Om .NET te begrijpen moet je weten wat er bedoeld wordt met een object, .NET is een objectgeoriënteerde omgeving.

Een object is een op zichzelf staande eenheid. Het houdt gegevens(data) vast en laat ons die gegevens door code die we schrijven manipuleren op een eenvoudige welgedefiniëerde manier. De beschrijving van een object leg je vast in een klasse (class definition). Om acties te ondernemen met gegevens van het object definiëren we in de klasse methoden.

De theorie hieromtrent leerde je reeds in de cursus C#.

12

Frank Horemans

Page 13: Cursus ASP.net 1

2.4 .Net Basisklassen

.NET bevat een omvangrijke bibliotheek aan klassen die we kunnen gebruiken in onze applicaties. Deze klassen bevatten code die klaar voor gebruik is, en ons veel codegeschrijf kan besparen. Klassen worden gegroepeerd in namespaces. Namespaces bevatten dus klassen die te maken hebben met eenzelfde functionaliteit.

In de namespace System.Drawing zitten bijvoorbeeld klassen die ons in staat stellen grafische objecten zoals cirkels en rechthoeken te tekenen. We kunnen deze basisklassen in onze eigen projecten invoegen.

2.5 Streefdoelen van ASP.net

Onafhankelijk werken van script-interpreters

Klassieke ASP werkt met behulp van scripttalen. Dit impliceerde een aantal nadelen: Code wordt geïnterpreteerd i.p.v. gecompileerd: de code wordt pas omgezet in machineinstructies op het moment dat die wordt uitgevoerd, wat performantievelies tot gevolg heeft. Met ASP.Net wordt wanneer een pagina de eerste keer wordt opgevraagd deze code gecompileerd in een .dll-assembly. Deze assembly wordt geplaatst in een submap %systemroot%/Micrososft.net/Framework/v1.n.nn/Temporary ASP.NET Files. Deze assembly bevat een klasse die werd afgeleid van de System.Web.UI.Page klasse. Deze klasse bevat alle code die gebruikt wordt om de respectievelijke pagina te openen en wordt uitgevoerd door het framework telkens de pagina wordt aangeroepen. De compilering van een pagina hoeft dus slechts één keer te gebeuren. Het enige wat nodig is, is wat hardeschijfruimte op de server. Je kan de locatie van deze map wijzigen door een tempdirectory attribuut op te nemen in het bestand machine.config (zie later). Wanneer een pagina wordt gewijzigd zal en nieuwe assembly worden samengesteld.

De code is nu typevast (variabelen moeten strikt getypeerd worden) en wordt dus gecompileerd.

Doordat ASP.NET pagina's werken met een extensie .aspx kan je op dezelfde server klassieke ASP en nieuwe ASP.NET pagina's gebruiken.

De hoeveelheid code verminderen om webapplicaties te bouwen

Door gebruik te maken van talloze voorgedefiniëerde servercontrols kan je de code in een webapplicatie drastisch verminderen in vergelijking met klassieke ASP of andere server-side talen. Je kunt ook je eigen servercontrols aanmaken waardoor code heel gemakkelijk opnieuw te gebruiken is.

ASP.net staat toe dat gebruikers bestaande functionaliteit uitbreiden / vervangen

Doordat het .NET model volledig gedefiniëerd is in het klassensysteem kan je zelf klassen afleiden op dat model of zelfs bestaande functionaliteit veranderen.

Taal is irrelevant (bijna)

Wanneer je ASP.NET gebruikt kan je als gebruiker vrij kiezen of je C#, VB.NET of zelfs J# wenst te gebruiken. Het is zelfs mogelijk om andere compilers in te stellen voor gebruik binnen het .NET Framework.

13

Frank Horemans

Page 14: Cursus ASP.net 1

Geen tools nodig

Zoals voor ASP heb je voor het ontwikkelen van ASP.NET pagina's geen ontwikkeltools nodig. Je kunt natuurlijk wel gebruik maken van een tool zoals Visual Studio.NET, maar het is zeker geen must, met een teksteditor kan je alle functionaliteit binnen het .NET Framework aanspreken.

2.6 ASP.net code schrijven

VS 2005

Maak een nieuwe Web Site locatie: ...\ASPNET20\Vogelvlucht

<SCRIPT>-BLOKKEN

Wanneer je serverside code in een webpagina opneemt, dan moet je deze code markeren om ze te onderscheiden van gewone HTML-code. Om ASP.NET code van HTML code te onderscheiden kan je gebruik maken van de script tag met het attribuut runat="server".

ASP.NET is een technologie waarin met verschillende talen kan worden gewerkt, bovenaan de pagina kan je met een Page-directive aangeven met welke taal je wilt werken :

<%@ Page language="c#" %>

Om een stuk server-side code te markeren gebruik je : <script language="c#" runat="server">

…C# declaraties …</script>

Wanneer je al een Page-directive hebt gebruikt mag je het attribuut language weglaten, vaak wordt het echter voor de duidelijkheid steeds vermeld. Binnen een script blok mogen enkel declaraties staan: stukken code die we later in de toepassing willen gebruiken wanneer een ander stuk code hen 'triggert". In zo'n script blok wordt bijvoorbeeld de Page_Load subroutine geplaatst die uitgevoerd wordt wanneer de pagina door de server geladen is.

<%@ Page Language="C#" %><script runat="server">

private void Page_Load(object sender, System.EventArgs e) {

Bericht.Text = "Welkom in de cursus ASP.net"; }

</script>

<html><head></head><body> <form runat="server"> <asp:Label id="Bericht" runat="server">Label</asp:Label> </form></body>

14

Frank Horemans

Page 15: Cursus ASP.net 1

</html>

Opmerking: wanneer je werkt met Visual Studio.net, hou dan in het achterhoofd dat dit programma standaard werkt met een andere techniek voor het plaatsen van ASP.net code: codebehind. Deze techniek komt spoedig aan de orde. Wens je echter deze voorbeelden te maken met VS.net, dan moet de waarde van het attribuut AutoEventWireUp op true(standaard) ingesteld zijn. Anders zal de Page_Load routine niet worden uitgevoerd.

Verplaats het script-blok:

<%@ Page Language="C#" %><html><head></head><body> <form runat="server"> <asp:Label id="Bericht" runat="server">Label</asp:Label> </form></body></html><script runat="server">

private void Page_Load(object sender, System.EventArgs e) {

Bericht.Text = "Welkom in de cursus ASP.net"; }

</script>

Je merkt dat het resultaat in de browser exact hetzelfde is. De routine Page_Load wordt steeds uitgevoerd vooraleer de server iets van HTML-code terugstuurt naar de browser. De webserver gaat in feite bij een pagina-aanvraag eerst onderzoeken of er script-blokken aanwezig zijn, de code in deze blokken moet steeds in subroutines aanwezig zijn. De positie van deze blokken in niet relevant, ze worden steeds eerst verwerkt.

Inline codeblokken

Het zou natuurlijk erg onhandig zijn mochten we steeds eerst alle dynamische informatie moeten laten verschijnen vooraleer statische HTML-elementen worden getoond. Je kan ASP.NET code ook inline gebruiken met de <% en %> tags (zoals in klassieke ASP).

<%@ Page Language="C#" %>

<html><head></head><body> Een HTML-lijn <br/> <% Response.Write("Een ASP.net-lijn<br/>"); %> Een tweede HTML-lijn<br/> <% Response.Write("Een tweede ASP.net-lijn<br/>"); %> Een derde HTML-lijn</body></html>

15

Frank Horemans

Page 16: Cursus ASP.net 1

Deze manier van coderen wordt echter afgeraden omdat de ASP.NET code tussen de HTML-code verstrikt raakt en daardoor moeilijk te hergebruiken en onderhouden is. Het is beter te werken met een <script>blok in combinatie met ASP.NET servercontrols. Dit komt verder in de cursus uitgebreid aan bod.

CodeBehind

Met de code behind techniek kan je de programmalogica scheiden van de inhoud van de pagina. Wij hebben in de voorbeelden tot hiertoe steeds gebruik gemaakt van inline code of scriptblokken: de programmalogica en inhoud van de pagina staan in eenzelfde bestand.

Dit voorbeeld demonstreert het werken met Codebehind. De programmalogica staat in een apart bestand (voor VB is dat een .vb - bestand, voor C# een .cs-bestand). De @Page directive in het aspx-bestand bevat een inherits-attribuut, waarbij wordt aangeduid dat we wensen te erven van de MijnCodeBehind-klasse. De klasse kan gevonden worden in het bestand mijncodebehind.cs zoals aangeduid in het CodeFile-attribuut. Belangrijk hierbij is dat je op deze manier slechts van één klasse kan overerven.

De eerste drie regels importeren een aantal belangrijke namespaces uit het .NET Framework. In een webpagina (aspx) worden die namespaces reeds geïmporteerd, echter niet in een .cs-file. Hierna maken we een klasse MijnCodeBehind, deze klasse erft van de Page-klasse uit de System.Web.UI namespace. De namespace werd reeds geïmporteerd, dus de naam van de klasse Page volstaat hier. De naam van de klasse (MijnCodeBehind) stemt natuurlijk overeen met de naam opgegeven in het inherits-attribuut van de @Page-directive in het aspx-bestand.

Dan zorgen we ervoor dat de controls die we wensen te gebruiken in het aspx-bestand gekend zijn in de klasse MijnCodeBehind door ze publiek te declareren. Daarna volgt de code voor de Page_Load methode.

CodeBehind.aspx <%@Page Inherits="MijnCodeBehind" src="MijnCodeBehind.cs" %><html><head></head><body> <form runat="server">

<asp:label id="bericht" runat="server" /> </form></body></html>using System;using System.Web.UI;using System.Web.UI.WebControls;

public class MijnCodeBehind : Page{

public Label bericht ;

public void Page_Load(Object Sender , EventArgs E){

bericht.Text = "Hallo ASP.net gebruiker";

16

Frank Horemans

Page 17: Cursus ASP.net 1

}}

Visual Studio 2005 gebruikt hier partial classes, waardoor de WebForm (aspx) en de codebehind (aspx.cs) als het ware één klasse vormen. Daardoor moeten de controls op de pagina (zoals het Label) niet meer gedeclareerd worden.

17

Frank Horemans

Page 18: Cursus ASP.net 1

3 ASP.NET : FORMULIEREN

1. Inleiding 2. Het http protocol 3. Html formulieren

3.1 Inleiding

Een van de taken die je als webontwikkelaar heel vaak zal uitvoeren is het opvragen en verwerken van informatie die de gebruiker je geeft.Welke informatie je ook wenst op te vragen, deze kan niet verwerkt worden met enkel HTML-code op de browser. Informatie die je wenst te gebruiken moet naar de webserver gestuurd worden voor verwerking.

Je kunt gegevens via een website versturen met behulp van formulieren. In HTML zijn er speciale tags om formulieren aan te maken. Deze elementen heb je al leren kennen in de cursus HTML, en kan je met ASP.NET blijven gebruiken. Daarenboven levert ASP.NET extra controls om formulieren af te handelen. Deze controls zijn een stuk krachtiger dan de gewone HTML-elementen, je kunt met de ASP.NET controls bijvoorbeeld informatie onthouden wanneer een pagina herladen wordt (wat stond er in een tekstvak, welke keuze werd in een keuzelijst gemaakt,…). In klassieke ASP moet je er steeds met eigen code voor zorgen dat bij het herladen deze elementen opnieuw gevuld worden.

De ASP.NET code die in dit hoofdstuk wordt behandeld dient enkel tot doel begrip te hebben van formulieren en formulierafhandeling. De code zal hierbij niet steeds uitvoerig worden uitgelegd, maar komt in latere hoofdstukken aan bod.

3.2 Het http protocol

Het Internet is een netwerk tot ontwikkeld is om informatie van de ene plaats naar de andere te brengen. Wanneer een browser een pagina wenst op te halen stuurt die een bericht naar de server. Dit bericht wordt verstuurd met het HTTP Protocol (Hypertext Transfer Protocol). Het bericht dat de browser stuurt naar de server is de HTTP Request. Wanneer de server dit bericht ontvangt, wordt het resultaat verstuurd naar de browser via de HTTP Response.

HTTP is een statusloos (stateless) protocol. HTTP weet dus niet of de HTTP request een alleenstaand bericht is of deel uit maakt van een grotere 'conversatie'. Het Internet zou heel log en traag worden mocht met een protocol worden gewerkt dat steeds alle verlopen aanvragen en connectie-eigenschappen bijhield. HTTP staat dus enkel in voor het leveren van een request bij een server en het terugbrengen van een response. HTTP kent ook geen prioriteiten en behandelt dus elke aanvraag als even belangrijk (een kwaadaardig programma kan dus 1000 keer per minuut een serveraanvraag doen, alle aanvragen worden gelijkwaardig behandeld).

Wanneer een request bij een server wordt ingediend bevat dit heel wat meer informatie dan enkel de gewenste URL. Ook de response van de server kan heel wat meer bevatten dan enkel de gewenste webpagina. Van deze functionaliteiten kan je handig gebruik maken met ASP.NET.

18

Frank Horemans

Page 19: Cursus ASP.net 1

Veel van deze extra informatie wordt automatisch door browser en server verstuurd, de gebruiker hoeft er zich dus niet om te bekommeren. Een HTTP request en een HTTP response bestaat in feite uit drie delen:

Http Request

Request Line

Een HTTP-commando Pad en bestandsnaam Versienummer van HTTP Vb. : GET/Testpagina.htm HTTP/1.1

Http header

Gegevens over het browsertype, tijd, taalinstellingen, ...

Http body

Data die een gebruiker wenst mee te delen aan de server. Hier zit de informatie die via formulieren met de methode "POST" wordt verstuurd. De methode GET gebruikt de querystring als deel van de URL. Meer hierover verder in de cursus.

Http Response

Response Line

Versienummer van HTTP Een statuscode die succes of mislukking van het request aanduidt Vb. : HTTP/1.1 200 OK

Http header Gegevens over het servertype, tijd, ...

Http body HTML en andere client-side code (vb. Javascript)

3.3 Html formulieren

Formulieren zijn in HTML een manier voor de gebruiker om informatie terug te sturen naar de server. Formulieren zijn in HTML omgeven door de <form> en </form> tags. Twee attributen zorgen voor het correct versturen naar de server:

Action: welke pagina moet de formulierdata ontvangen Method: De HTTP-methode waarmee we de formuliergegevens versturen.

19

Frank Horemans

Page 20: Cursus ASP.net 1

De methode GET<html><head>

<title>Formulier : GET</title></head><body><form action="volgende.aspx" method="get">Geef je naam in : <input name="naam" type="text"><br/><input type="submit" value="Verstuur"></form></body></html>

Wanneer je dit bestand opent in een browser kan je een naam invullen in het tekstvak.

Druk op de verstuurknop:

20

Frank Horemans

Page 21: Cursus ASP.net 1

Je krijgt een foumelding! Dit is normaal in dit voorbeeld. Belangrijk is echter een kijkje te nemen in de adresbalk. Je merkt dat in de adresbalk de informatie die je in het formulier hebt ingevuld te lezen is. De informatie is voorlopig echter nutteloos. De formulierinformatie werd, gekoppeld aan de url, verstuurd naar de webserver wanneer de gebruiker op de verstuurknop drukte. De webserver gaat op zoek naar de pagina die in het action-attribuut van de form-tag was vermeld. Aangezien de pagina volgende.aspx niet bestaat krijgen we een foutmelding. Een browser handelt formulierinformatie niet zelf af, deze afhandeling gebeurt op de server.

We maken nu de pagina waarop de formulierafhandeling moet gebeuren :

volgende.aspx<%@ Page Language="C#" %><script runat="server">

private void Page_Load(object sender, System.EventArgs e) {

Bericht.Text = "Welkom in de cursus ASP.net, " +Request.QueryString["naam"] +"!"; }

</script>

<html><head></head><body> <asp:Label id="Bericht" runat="server">Label</asp:Label></body></html>

Wanneer je deze pagina opslaat als volgende.aspx in dezelfde map als formget.html kan je het formulier wel aan het werk zien:

De opdracht Request.Querystring["naam"] in volgende.aspx zorgt ervoor dat op de server de querystring gelezen wordt en de waarde gekoppeld aan het veld naam wordt opgehaald.

21

Frank Horemans

Page 22: Cursus ASP.net 1

Deze waarde wordt in een zin geplaatst en daarna op het scherm gezet in een label. Bekijk de broncode van deze pagina:

Zoals je ziet is alle ASP.NET code verdwenen. De server heeft de code uitgevoerd en HTML-output gegenereerd.

De methode POST

formpost.html<html><head> <title>Formulier : POST</title></head><body> <form action="volgende2.aspx" method="post"> Geef je naam in : <input type="text" name="naam" /> <br /> <input type="submit" value="Verstuur" /> </form></body></html>

volgende2.aspx<%@ Page Language="C#" %><script runat="server">

private void Page_Load(object sender, System.EventArgs e) {

Bericht.Text = "Welkom in de cursus ASP.net, " +Request.Form["naam"] +"!"; }

</script>

<html><head></head><body>

<asp:Label id="Bericht" runat="server">Label</asp:Label>

</body>

22

Frank Horemans

Page 23: Cursus ASP.net 1

</html>

Het enige verschil in de code is de opdracht Request.Form i.p.v. Request.Querystring. Wanneer je de resultaatpagina in de browser ziet merk je dat de informatie deze keer niet in de adresbalk te zien is. De informatie werd nu verstuurd in de body van de HTTP requestinformatie, deze informatie is dus ook bereikbaar voor ASP.NET.

GET of POST

Het gebruik van de methode GET of POST hangt af van de situatie. Bij GET wordt de informatie in de querystring als deel van de URL opgegeven. Daardoor is het mogelijk de pagina met argumenten te bookmarken, wat bij POST niet mogelijk is. Vandaar dat veel zoekmotoren de methode GET gebruiken. Het is echter aan te raden bij formulieren waar paswoorden of andere gevoelige informatie wordt gevraagd de methode POST te gebruiken.

HTML formulierelementen

HTML kent natuurlijk een ganse reeks formulierelementen, deze heb je leren kennen in de cursus HTML4.

Deze formulierelementen ondersteunen nog andere attributen, de INPUT-tag kent bv. de attributen name, type, value en checked. In de voorbeelden op de vorige pagina's heb je reeds een tekstbox leren gebruiken. Algemeen werken deze formulierelementen als volgt : Bij versturen van het formulier (drukken op de submit-button) wordt de pagina die in het action-attribuut van de form-tag staat, opgevraagd. Aan deze pagina worden de namen en waarden (name=value pairs) doorgegeven via de querystring (methode GET) of de request-body (methode POST). Als je formulieren wenst af te handelen op de server geef je dus de elementen een naam (name) en een waarde (value).

Uitgebreid voorbeeld

formulierelementen.aspx<html><head></head><body><form action="gegevens.aspx" method="post"><p><strong>Gelieve volgende gegevens in te vullen :</strong></p><table width="300"><tr> <td>Naam :</td> <td><input name="naam" type="text" /></td></tr><tr> <td>Paswoord :</td> <td><input name="pwd" type="password" /></td></tr><tr> <td>Gebruik :</td> <td> <input name="gebruik" type="checkbox" " value="T" checked />Thuis <input name="gebruik" type="checkbox" " value="W" />Werk <input name="gebruik" type="checkbox" " value="S" />school

23

Frank Horemans

Page 24: Cursus ASP.net 1

</td></tr><tr> <td>Geslacht :</td> <td> <input name="gesl" type="radio" value="V" checked />Vrouw <input name="gesl" type="radio"" value="M" />Man </td></tr><tr> <td>Niveau :</td> <td> <select name="niv" size="3"> <option value="1" selected>Beginner</option> <option value="2">Geoefend</option> <option value="3">Geavanceerd</option> </select> </td></tr><tr> <td>Opmerkingen :</td> <td> <textarea name="opm">Tik hier je opmerkingen</textarea> </td></tr><tr> <td><input type="reset" value="Reset" /></td> <td><input type="submit" value="verstuur" /></td></tr></table></form>

In je browser levert deze code :

24

Frank Horemans

Page 25: Cursus ASP.net 1

Om de formuliergegevens af te handelen maken we de pagina gegevens.aspx, deze naam werd opgegeven in het action-attribuut van bovenstaand formulier.

gegevens.aspx<%@ Page Language="C#" %><html><head> <title>Gegevens</title></head><body> Uw gegevens : <table> <tbody> <tr> <td> Naam :</td> <td> <%= Request.Form["naam"] %></td> </tr> <tr> <td> Paswoord :</td> <td> <%= Request.Form["pwd"] %></td> </tr> <tr> <td>

25

Frank Horemans

Page 26: Cursus ASP.net 1

Gebruik :</td> <td> <%= Request.Form["gebruik"] %></td> </tr> <tr> <td> Geslacht :</td> <td> <%= Request.Form["gesl"] %></td> </tr> <tr> <td> Niveau :</td> <td> <%= Request.Form["niv"] %></td> </tr> <tr> <td> Opmerkingen :</td> <td> <%= Request.Form["opm"] %></td> </tr> </tbody> </table></body></html>

Zoals je merkt is de ASP.NET en de HTML-code volledig in elkaar verweven. Dit voorbeeld toont je eigenlijk hoe je het beter niet doet. Deze manier van coderen werd soms gebruikt bij het maken van pagina's in klassieke ASP. ASP.NET geeft je mogelijkheden om code beter te structureren.

26

Frank Horemans

Page 27: Cursus ASP.net 1

Hier hebben we gebruik gemaakt van de gewone HTML formulierelementen. Je kan die zoals je ziet nog steeds gebruiken met ASP.NET, er zijn zelfs situatie waarin dit aan te raden is (bv. wanneer client-side code moet worden uitgevoerd).

Voor het server-side afhandelen van pagina's maak je in ASP.NET echter beter gebruik van Servercontrols of Web Form Controls.

27

Frank Horemans

Page 28: Cursus ASP.net 1

4 ASP.NET : HTML SERVER-CONTROLS

1. Wat zijn HTML-servercontrols ? 2. Een gewoon HTML-formulier 3. ASP.net serverformulier 4. __VIEWSTATE 5. Actie ondernemen 6. Achtergrond 7. Viewstate aangeven 8. Html servercontrols en stijlen 9. Reageren op events

4.1 Wat zijn HTML-servercontrols ?

We weten dat wanneer een pagina, die een eerste keer wordt aangevraagd op de server, wordt gecompileerd in een klasse (binnenin een .dll-bestand). Deze klasse kan uitgevoerd worden telkens de pagina wordt opgevraagd. De server stuurt zo alle statische HTML en client-side code terug naar de client. We hebben hiermee nu geen interactie meer op de server.

Controls die echter gemarkeerd worden met het attribuut runat="server" worden op de server objecten van de klasse Page. Dit betekent dat je server-side code kan schrijven die deze objecten beïnvloedt : we hebben toegang tot de eigenschappen en methoden van deze objecten en kunnen op de server reageren op events die zich voordoen binnen deze objecten (klikken, keuzes die gemaakt worden,...). Om op events in formulierelementen te reageren op de server maakt ASP.NET gebruik van de postback-architectuur : de pagina wordt naar dezelfde pagina op de server teruggestuurd wanneer controls worden beïnvloed. Wanneer de gebruiker op een knop op een formulier klikt wordt het formulier opnieuw naar de server gestuurd (postback) en een eventroutine wordt op de server uitgevoerd. Belangrijk is ook het feit dat Server Controls zich niet beperken tot HTML-formulierelementen, je kunt ook andere HTML-tags als server-control markeren !

4.2 Een gewoon HTML-formulier

Wanneer je het onderstaande formulier verstuurt, wordt dezelfde pagina opnieuw geladen. Merk op dat alle gegevens die je hebt ingevuld verloren zijn gegaan: http is stateless !

htmlform.html<html><head>

<title>HTML-form</title></head><body><form id="Form1" action="htmlform.html"><table><tr> <td>Naam :</td> <td><input type="text" id="naam"></td></tr><tr> <td>Voornaam : </td>

28

Frank Horemans

Page 29: Cursus ASP.net 1

<td><input type="text" id="voornaam"></td></tr><tr> <td>Aantal :</td> <td><select id="aantal">

<option value="1">1</option> <option value="2">2</option> <option value="3">3</option>

</select></td>

</tr></table>

<input type="submit" value="klik me"> </form></body></html>

4.3 Een ASP.net serverformulierServerForm.aspx

<%@ PAGE language="c#" %><html><head>

<title>Serverform</title></head><body><form id="Form1" runat="server"><table><tr> <td>Naam :</td> <td><input type="text" id="naam" runat="server"></td></tr><tr> <td>Voornaam : </td> <td><input type="text" id="voornaam" runat="server"></td></tr><tr> <td>Aantal :</td> <td><select id="aantal" runat="server">

<option value="1">1</option> <option value="2">2</option> <option value="3">3</option>

</select></td>

</tr></table>

<input type="submit" value="klik me" runat="server"></form></body></html>

4.4 __VIEWSTATE

Bekijk voor bovenstaande pagina de broncode in de browser:

29

Frank Horemans

Page 30: Cursus ASP.net 1

<html><head>

<title>Serverform</title></head><body><form name="Form1" method="post" action="ServerForm.aspx" id="Form1"><div><input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTk4NDU0ODIyMWRkl7VvKXMytCE+87WVlXk5UmBICJQ=" /></div>

<table><tr> <td>Naam :</td> <td><input name="naam" type="text" id="naam" /></td></tr><tr> <td>Voornaam : </td> <td><input name="voornaam" type="text" id="voornaam" /></td></tr><tr> <td>Aantal :</td> <td><select name="aantal" id="aantal">

<option value="1">1</option><option value="2">2</option><option value="3">3</option>

</select></td>

</tr></table>

<input name="Submit1" type="submit" id="Submit1" value="klik me" />

<div>

<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBQKKw9nZBwLn3YvMDgKEhan0BwLqkpGKCgLVo8avDpzM1csbPfbYOcjuvaxCmzEqJ12a" /></div></form></body></html>

Aangezien de browser enkel HTML en client-side code zoals Javascript ondersteunt is er van de server-side ASP.NET code geen spoor te vinden. Je merkt echter dat de code er in de browser helemaal anders uitziet dan de code die werd uitgevoerd op de server.

Elk element op de pagina dat een attribuut runat="server" draagt wordt bij het aanroepen van de pagina door de server onderhanden genomen.

De tags verliezen hun runat-attribuut (hier is de browser niks mee) maar krijgen eventueel een aantal andere attributen. Je merkt in de form-tag dat de method is ingesteld op post en de action op de naam van de huidige pagina. Vooral dit laatste is heel belangrijk : het is een illustratie van de postback-architectuur waarvan zopas sprake.

Je merkt ook dat de formulierelementen (form en input) een name en/of id hebben gekregen. Deze naam dient om bij het terugposten van de pagina te zien of er aan deze

30

Frank Horemans

Page 31: Cursus ASP.net 1

control iets is veranderd (moet een event getriggerd worden ?). Als de server moet bepalen of er een verandering is opgetreden, dan moet je bij het terugposten de huidige situatie ook meegeven, want het http-protocol is 'stateless' en behandelt elke aanvraag als volstrekt onafhankelijk.

Vandaar het hidden veld __VIEWSTATE : hierin staat in een voor de ASP.NET-server begrijpelijke code de situatie zoals nu op het scherm is afgebeeld. Doe je als gebruiker een actie die het versturen van het formulier tot gevolg heeft, dan kan de server bepalen wat er veranderd is en op die actie reageren.

Wanneer je het formulier invult en verstuurd zal je merken dat alle informatie die je hebt ingevuld bewaard is gebleven!

4.5 Actie ondernemen

We maken een kleine toepassing waarbij we detecteren of een gebruiker op een knop heeft geklikt.

<%@ PAGE language="c#" %><html><head>

<title>Knop</title><SCRIPT language="c#" runat="server">private void KnopKlik(object sender, System.EventArgs e) {

tekstvak.InnerHtml = "U heeft op de knop geklikt !";}</SCRIPT>

</head><body><form runat="server">

<p><div style="border:solid;border-width:1;width:200" id="tekstvak" runat="server"/></p>

<p><input type="submit" value="klik me" onserverclick="KnopKlik" runat="server"></p></form></body></html>

Je kan met het attribuut onserverclick het klikken op de submit-button server-side opvangen.

4.6 Achtergrond

HTML Server Controls zijn elementen die gedefiniëerd zijn in de namespace System.Web.UI.HtmlControls. Hierin zitten een aantal basisklassen waarvan de controls overerven (meer over klassen en overerving verderop in de cursus). De basisklasse voor alle HTML Controls is de System.Web.UI.HtmlControls.HtmlControl klasse. Deze klasse bevat eigenschappen, methoden die gemeenschappelijk zijn voor alle HTML Controls.

Via de Visual Studio.net 2003 Documentation > .NET Framework > Reference > Class Library of met de ClassBrowser die wordt meegeleverd met de .NET Web Matrix kan je deze klassen onderzoeken en kijken welke eigenschappen en methodes voorhanden zijn.

31

Frank Horemans

Page 32: Cursus ASP.net 1

Opmerking : de eigenschap InnerHtml die we in het vorig voorbeeld hebben gebruikt, maakt deel uit van de System.Web.UI.HtmlControls.HtmlContainerControl klasse, die gebruikt wordt voor containerelementen : tags die een sluittag moeten hebben : I, B, DIV, ... Met behulp van de classbrowser kanje zien dat een aantal elementen een voorgedefiniëerde klasse hebben binnen System.Web.UI.HtmlControls: hyperlinks (<,a runat="server">) worden bijvoorbeeld op de server vertaald als HtmlAnchor-klassen.

Naast deze voorgedefiniëerde klassen bestaan nog HTML-elementen die hier geen tegenhanger vinden. Deze elementen worden dan omgezet in een object van de System.Web.UI.HtmlControls.HtmlGenericControl klasse. Deze klasse dient dus voor het afhandelen van Server Controls die geen klasse hebben binnen System.Web.UI.HtmlControls.

4.7 Viewstate aangeven

Wanneer een control gemarkeerd is met runat="server" wordt de waarde ervan bewaard bij versturen van de pagina naar de browser, in het verborgen formulierveld __VIEWSTATE. Soms zal je voor een bepaalde control niet willen dat deze status wordt bewaard. Door het attribuut EnableViewState op false in te stellen wordt voor de respectievelijke control geen status bewaard.

4.8 Html Servercontrols en stijlen

Je kunt met ASP.NET Server Controls ook gebruik maken van stylesheets en de opmaak vanop de server vastleggen:

Stijl.aspx<%@ PAGE language="c#" %><html><head>

<title>Stijl</title><SCRIPT language="c#" runat="server">private void Page_Load(object sender, System.EventArgs e) {

info.InnerHtml = "Opgemaakte tekst";info.Style["font-family"] = "Courier new";info.Style["font-weight"] = "Bold";info.Style["font-size"] = "18pt";info.Style["margin-left"] = "4cm";

}

</SCRIPT></head><body><div id="info" runat="server" /></body></html>

Bron in de browser: <html><head>

<title>Stijl</title>

</head><body>

32

Frank Horemans

Page 33: Cursus ASP.net 1

<div id="info" style="font-family:Courier new;font-weight:Bold;font-size:18pt;margin-left:4cm;">Opgemaakte tekst</div></body></html>

4.9 Reageren op events

Wanneer we gebruik maken van Server Controls worden acties die de gebruiker onderneemt (klikken op een knop, een keuze veranderen in een lijst) op de server afgehandeld. Er zijn twee events die je hiervoor kan gebruiken : ServerClick en ServerChange.

Serverclick

Dit event heb je reeds leren kennen in knop.aspx, hier gaan we er wat meer in detail op in.

Serverclick<%@ PAGE language="c#" %><html><head>

<title>Serverclick</title><SCRIPT language="c#" runat="server">private void MijnCode(Object objSender,EventArgs objArgs){ Control c = (Control)objSender;

divResultaat.InnerHtml += "Klik op knop : <B>" +c.ID +"</B><BR>";

}

private void MijnfiguurCode(Object objSender ,ImageClickEventArgs objArgs){

HtmlInputImage c = (HtmlInputImage)objSender; divResultaat.InnerHtml += "Klik op figuur " +c.ID +" <I>--> xpos : " +objArgs.X +" / ypos : " +objArgs.Y +"</I><BR>";}</SCRIPT>

</head><body><form runat="server">

<input id="MijnKnop" type="button" value="Mijn knop" onserverclick="MijnCode" runat="server" />

<input id="MijnSubmitKnop" type="submit" value="Mijn submitknop" onserverclick="MijnCode" runat="server" />

<input id="figuur" type="image" src="../images/vraag.jpg" onserverclick="MijnfiguurCode" runat="server" /></form><div id="divResultaat" runat="server" /></body></html>

Telkens op een knop of op de figuur wordt geklikt verschijnt een boodschap op het scherm. Wanneer op een van de knoppen wordt geklikt wordt de routine MijnCode gestart, wanneer je op de figuur klikt wordt MijnFiguurCode uitgevoerd. Beide routines voegen een zin toe aan de InnerHtml eigenschap van de divisie

33

Frank Horemans

Page 34: Cursus ASP.net 1

divResultaat. Belangrijk hierbij is dat je de code voor het afhandelen van een event aan meerdere controls kan koppelen, zoals hier met de twee knoppen.

De eventhandler-routines ontvangen twee parameters :

Het eerste is een referentie naar het object dat de event heeft uitgevoerd : Object objSender.

Het tweede is een Args-object dat meer informatie bevat over de uitgevoerde actie. o Bij de HtmlInputButton is dat een EventArgs object : EventArgs objArgs. o Bij de HtmlInputImage control (de figuur dus) is dat een

ImageClickEventArgs-object, dat intern twee parameters X en Y bevat die de coördinaten aangeven van de muisaanwijzer toen de figuur werd aangeklikt.

Serverchange

Dit event kan je gebruiken bij controls die niet automatisch voor een repost naar de server zorgen, waar je als gebruiker m.a.w. niet op klikt : HtmlInputText, HtmlInputCheckBox, HtmlInputRadioButton, HtmlSelect,...

Wanneer sinds de vorige post iets aan deze control is veranderd, wordt het ServerChange event uitgevoerd.

ServerChange.aspx<%@ PAGE language="c#" %><html><head>

<title>ServerChange</title><SCRIPT language="c#" runat="server">private void MijnCode(Object objSender ,EventArgs objArgs){ Control c = (Control)objSender; divResultaat.InnerHtml += "Verandering vastgesteld : <B>" +c.ID

+"</B><BR>";}private void MijnLijstCode(Object objSender,EventArgs objArgs){ HtmlSelect c = (HtmlSelect)objSender;

divResultaat.InnerHtml += "Verandering vastgesteld : <B>"+c.ID +"</B>" +"</I><BR>"+"Index = <i>" +c.SelectedIndex +"</i><BR>"+"Tekst = <i>" +c.Items[c.SelectedIndex].Text +"</i><BR>"+"Waarde = <i>" +c.Items[c.SelectedIndex].Value +"</i><BR>";

}</SCRIPT>

</head><body><form runat="server">

<input id="MijnTekst" type="text" value="Standaardtekst" onserverchange="MijnCode" runat="server" />

<select id="MijnLijst" onserverchange="MijnLijstCode" runat="server">

<option value="waarde 1">Optie 1</option><option value="waarde 2">Optie 2</option><option value="waarde 3">Optie 3</option>

</select><input id="MijnCheckBox" type="checkbox" onserverchange="MijnCode"

runat="server" /><input type="submit" value="verstuur" />

34

Frank Horemans

Page 35: Cursus ASP.net 1

</form><div id="divResultaat" runat="server" enableviewstate="false"/></body></html>

35

Frank Horemans

Page 36: Cursus ASP.net 1

5 ASP.NET : WEB CONTROLS

1. Wat zijn Web Controls ? 2. Visual Studio.net en Web Controls 3. Overzicht elementaire Web Controls 4. Autopostback 5. Input Validation Controls 6. List Controls 7. Oefeningen

5.1 Wat zijn Web Controls ?

In plaats van gebruik te maken van de HTML Controls is er een set van controls aanwezig genaamd Web Form Controls. Ze zijn gedefiniëerd in de namespace System.Web.UI.WebControls.

De reden voor deze extra set controls is dat HTML-controls veelal attributen ondersteunen met verwarrende namen : het size-attribuut geeft je bijvoorbeeld in een listbox het aantal zichtbare rijen (onder elkaar), in textbox stelt dit attribuut de breedte in. Van een textarea wordt de breedte dan weer aangegeven met het rows-attribuut. Je merkt, een heel chaotische naamgeving van attributen.

Met de Web Form Controls beschik je over een set server-side controls die consequent zijn in het gebruik van attributen. Deze controls worden bij uitvoer naar de browser vertaald in de respectievelijke HTML-elementen.

5.2 Visual Studio.net 2005 en Web Controls

Toepassing

De Web Controls worden door VS.net als standaardelementen gebruikt. Het is dus hier dat je kan inpikken in de cursus en kan meewerken met Visual Studio.net.

Wij werken in VS 2005 met de codebehind-techniek, een manier om de opmaakcode (plaatsing van de elementen) en logische code van elkaar te scheiden. We maken een kleine toepassing ter illustratie:

Kies File > new > Web Site Kies een ASP.Net Web Site Geef als location: file system: .../H5 (map voor hoofdstuk 5) Rechtsklik Default.aspx en hernoem tot KlikForm.aspx Plaats vanuit de toolbox een button op de pagina:

o Kies eigenschappen (F4) o ID: CmdToonBericht, Text: Klik me

Plaats vanuit de toolbox een label op de pagina:

o Kies eigenschappen (F4) o ID: LblKlik, BorderStyle: solid; BorderWidth: 1px

36

Frank Horemans

Page 37: Cursus ASP.net 1

Bekijk de source:

o het label werd een asp:Label o de knop werd een een asp:Button o De eigenschappen die je hebt ingesteld vind je terug als attributen in de

respectievelijke tag

Dubbelklik de knop

o Je komt terecht in een ander bestand: KlikForm.aspx.cs Dit is de codebehind-file voor het bestand KlikForm.aspx: in deze file zal alle programmacode voor de pagina komen te staan.

o je kan nu code schrijven in de routine CmdToonBericht_Click: o LblKlik.Text = "Er werd geklikt !";

Voer de toepassing uit. Vergeet niet de broncode van de resultatenpagina eens te bekijken, alle

onbestaande HTML-attributen zijn verdwenen en werden ingewisseld voor standaard HTML/CSS-eigenschappen.

CodeBehind

Het is belangrijk in te zien hoe de codebehind-techniek werkt:

Het bestand KlikForm.aspx.cs bevat een klasse _Default, deze klasse erft over van System.Web.UI.Page: de basisklasse voor elke asp.net pagina. De klasse _Default bevat dus door overerving alle methoden en eigenschappen van de klasse Page.

Sinds C# 2.0 wordt gewerkt met een gedeeltelijke klassen of partial classes: een manier om een klasse te splitsen over verschillende bestanden. Concreet zal het .Net FrameWork bij het uitvoeren van een pagina een klasse genereren die objectreferenties bevat naar alle objecten die we op een pagina KlikForm.aspx hebben geplaatst (in het eerste voorbeeld een Button en een Label). Deze klasse wordt samengevoegd met onze eigen CodeBehind-klasse _Default in KlikFom.aspx.cs.

Vandaar dat we in de CodeBehind zonder probleem kunnen verwijzen naar objecten van de webpagina, als staan deze objecten er niet expliciet gedeclareerd.

5.3 Elementaire ASP.net Web Form Controls

Wanneer je werkt met de Web Form Controls, dan zal je merken dat deze algemeen in de code worden weergegven door een tag die start met asp:.

Er zijn heel wat Web Form Controls. Wat je zeker moet inzien is dat de browser deze tags niet kent. Deze tags dienen op de server verwerkt te worden en te worden omgezet in correcte HTML-tags.

37

Frank Horemans

Page 38: Cursus ASP.net 1

Op deze manier zullen wij verderop in de cursus onze eigen controls maken: we kiezen een eigen naam voor de tag en leren de server hoe de control moet worden omgezet in HTML/javascript - code.

WebControl Maakt HTML-tag

ASP:Hyperlink A

ASP:LinkButton A met IMG

ASP:Image img

ASP:Panel div

ASP:Label span

ASP:Button input type="submit" of "button"

ASP:Textbox input type="text" of "password" of textarea

ASP:CheckBox input type="checkbox"

ASP:RadioButton input type="radio"

ASP:ImageButton input type="image"

ASP:table table

... ...

38

Frank Horemans

Page 39: Cursus ASP.net 1

Elk van deze controls heeft tal van eigenschappen, het is niet de bedoeling in deze cursus om elke control gedetailleerd te beschrijven. Het is wel algemeen zo dat de eigenschappen van een control ingesteld kunnen worden via het eigenschappenvenster (F4), via de source-code, maar ook runtime kunnen aangepast worden in methodes in een codebehind file.

Voorbeeldtoepassing: afmeting en kleur van een Panel veranderen

Maak een toepassing waarbij je met behulp van twee knoppen een divisie breder kan maken en de kleur ervan kan veranderen.

Oplossing: in een nieuwe Web Site plaats je volgende controls op de pagina:

Een Panel (ID: Paneel - BorderStyle: Solid - BorderWidth: 1px) Via de 'design mode' verander je de tekst in het Panel in "Ik ben een paneel"

Een Button (ID: CmdBreder - Text: Maak Breder) Een Button (ID: CmdKleur - Text: Andere Kleur) Een HiddenField (ID: HFteller - Value: 0 )

Zorg voor de volgende code in de CodeBehind-file:

...using System.Drawing;...private void CmdBreder_Click(object sender, System.EventArgs e){

//Paneel breder makenPaneel.Width = Unit.Pixel((int)Paneel.Width.Value +

5);}

private void CmdKleur_Click(object sender, System.EventArgs e){

//definieer de verschillende kleurenstring[] kleuren = { "red", "blue", "black", "pink", "white" };

//lees de huidige waarde van de teller (verborgen formulierveld)int teller = Convert.ToInt32(HFteller.Value);

//teller ophogen, indien te hoog weer op nulif (++teller >= kleuren.Length) teller = 0;

//Paneel instellen op juist kleurPaneel.BackColor = Color.FromName(kleuren[teller]);

//Tellerwaarde wegschrijven in verborgen formulierveldHFteller.Value = teller.ToString();

}

Belangrijk is hierbij de techniek met een verborgen veld om de waarde van de teller te bewaren. Met een gewone variabele kan je geen informatie tussen verschillende pagina-aanvragen bewaren: http is stateless.

39

Frank Horemans

Page 40: Cursus ASP.net 1

We zullen later zien dat er hiervoor wel nog andere technieken bestaan dan het werken met verborgen velden.

Een belangrijke opmerking hierbij: deze toepassing leent er zich in principe beter toe om client-side met bijvoorbeeld javascript te worden opgelost. Het is belangrijk dat je goed inziet dat telkens wanneer je in deze toepassing de breedte of de kleur van het Paneel wijzigt, er een repost naar de server gebeurt, dit is het PostBack-principe van ASP.net !

5.4 AutoPostBack

Bepaalde ASP.NET Web Form Controls (TextBox, CheckBox, RadioButton), en ook alle list controls verderop in de cursus hebben een eigenschap AutoPostBack. Deze eigenschap stelt je in staat om bij een verandering in de control het formulier automatisch naar de server te laten terugsturen.

AutoPostBack.aspx bevat:

CheckBox (ID:CB - AutoPostBack: true - Text:Aankruisvakje) RadioButton (ID:RB1 - AutoPostBack: true - Text: Radio1 - GroupName: radio) RadioButton (ID:RB12- AutoPostBack: true - Text: Radio2 - GroupName: radio) Label (ID:L - Randstijl en kleurtjes kiezen) CB, RB1 en RB2: stel via de eigenschappen > events voor de eigenschap

CheckedChanged in: MijnCode, we gebruiken een gemeenschappelijke eventroutine voor de drie controls.

40

Frank Horemans

Page 41: Cursus ASP.net 1

AutoPostBack.aspx.csusing System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;

namespace AutoPostBack{

public partial class AutoPostBack : System.Web.UI.Page{

private void Page_Load(object sender, System.EventArgs e){

}

private void MijnCode(object sender, System.EventArgs e){

CheckBox c = (CheckBox)sender;

41

Frank Horemans

Page 42: Cursus ASP.net 1

L.Text += "Verandering vastgesteld in " +c.ID +"<br>De waarde is nu: " +c.Checked+"<br>Tekstwaarde: " +c.Text +"<hr>";

}

}}

Wanneer je de broncode opvraagt in de browser, dan merk je dat er client-side javascriptcode werd gegenereerd die ervoor zorgt dat formuliergegevens worden verstuurd wanneer de gebruiker een actie onderneemt.

Bij een repost naar de server worden de verborgen formuliervelden __EVENTTARGET en __EVENTARGUMENT naast __VIEWSTATE meegestuurd. Aan de hand van deze formuliervelden kan de server uitmaken welk control werd beïnvloed en welke server-side code moet worden uitgevoerd. In dit voorbeeld wordt bij het klikken (dus eigenlijk veranderen) van het aankruisvakje of een selectierondje de methode MijnCode uitgevoerd.

In deze routine typecasten we het eerste ontvangen argument van de klasse Object naar CheckBox: we zijn zeker dat het object dat de actie veroorzaakt tot deze klasse behoort (RadioButton erft over van CheckBox).

Een RadioButton is dus in feite afgeleid van een CheckBox in ASP.NET. Een RadioButton heeft een extra eigenschap : GroupName. Dit resulteert client-side in het name-attribuut voor de RadioButton. Gekoppelde radiobuttons (een groep waarin je maar eentje kan selecteren) geef je dus dezelfde waarde voor GroupName.

Merk op dat wanneer je op het reeds geselecteerde selectierondje klikt de pagina ook wordt teruggestuurd maar nu wordt MijnCode niet uitgevoerd

5.5 Input Validation Controls

Overzicht

Een van de vermoeiendste taken voor een ontwikkelaar is het controleren of de input van de user beantwoorde aan de gestelde vereisen. Om dit te vergemakkelijken werden in ASP.net de User Input Controls voorzien:

Control Omschrijving

asp:RequiredFieldValidatorControleert of een formulierveld een 'value' bevat. De waarde mag niet leeg zijn.

asp:RangeValidator Controleert of de waarde van een control binnen een numeriek of alfanumeriek bereik

42

Frank Horemans

Page 43: Cursus ASP.net 1

ligt.

asp:CompareValidator

Controleert of de waarde van de gevalideerde control overeenkomt met de waarde van een andere control of een specifieke waarde. Het gegevenstype en vergelijkingsoperator kunnen gekozen worden. Als de gevalideerde control geen waarde bevat, dan gebeurt er geen validatie.

asp:RegularExpressionValidatorControleert of de gevalideerde waarde beantwoord aan een reguliere expressie. Als de control leeg is dan is er geen validatie.

asp:CustomValidatorDoet een door de gebruiker gedefiniëerde controle op een control (client-side, server-side of allebei).

asp:ValidationSummaryGeeft een overzicht van de huidige validatiefouten.

Achtergrond

Alle validatiecontrols erven van de basisklasse BaseValidator die deel uitmaakt van de klasse System.Web.UI.WebControls.

Elke validatiecontrol heeft daar naast specifieke eigenschappen en methoden (en voor de CustomValidatorcontrol ook een event).

De input validation controls kunnen zowel client- als serverside controle op gegevens uitvoeren. Om client-side controle uit te voeren maken de formulierelementen gebruik van Javascript. De benodigde javascript-routines staan in het bestand aspnet_client\system_web\versie_n\WebUIValidation.js.

Heb je dit bestand niet, dan kopiëer je de map aspnet_client uit \inetpub\wwwroot of gebruik je aspnet_regiis -c (bevindt zich in C:\WINDOWS\Microsoft.NET\Framework\versie_n) vanaf de command prompt om deze bestanden aan te maken.

Input Validation Controls Gebruiken

Deze Web Form Controls hebben tal van verschillende eigenschappen. De belangrijkste:

43

Frank Horemans

Page 44: Cursus ASP.net 1

Eigenschap Betekenis

Display

Dynamic: de control neemt enkel plaats in als hij zichtbaar is

Static: voor de control wordt steeds plaats gereserveerd

None: de control wordt niet getoond (is handig wanneer je met een ValidationSummary werkt)

ID Naam voor de validatiecontrol

ControlToValidateDe control die aan een validatie wordt onderworpen

ErrorMessageBericht dat wordt getoond als een foutieve waarde is ingegeven

EnableClientScript Client-side validatie instellen

Enabled Server-side validatie instellen

ControlToCompareBij CompareValidator: control waarmee vergeleken wordt

ValueToCompare, Operator, Type

Bij CompareValidator: instellen met welke type en waarde er moet worden vergeleken, en hoe er vergeleken moet worden

MaximumValue Bij RangeValidator: maximumwaarde

MinimumValue Bij RangeValidator: minimumwaarde

ValidationExpressionBij RegularExpressionValidator: expressie die gebruikt wordt voor de controle

OnServerValidateBij CustomValidator: routine voor afhandelen van de server-side controle

ClientValidationFunctionBij CustomValidator: routine voor afhandelen van de client-side controle

HeaderText Bij ValidationSummary: koptekst voor foutrapport

ShowSummaryBij ValidationSummary: foutrapport weergeven of verbergen

44

Frank Horemans

Page 45: Cursus ASP.net 1

DislayModeBij ValidationSummary: layout voor het foutrapport - List, BulletList of SingleParagraph

Validatie controleren

Je kan server-side detecteren of controles goed zijn verlopen via de IsValid-property van het Page-object (de eigenlijke webpagina).

Validatie uitschakelen

Stel dat je een knop in het formulier wil aanbrengen waarmee de gebruiker het invullen van een formulier kan annuleren, dan zorgt deze knop standaard voor een postback naar de server en zal deze zorgen voor validatie. Je kan ervoor zorgen dat na het indrukken van de knop geen validatie gebeurt door de eigenschap CausesValidation op false in te stellen.

5.6 List Controls

Overzicht

Met deze server-side controls kan je lijsten genereren die veelal SELECT-elementen in HTML als resultaat geven. Er zijn echter heel krachtige List-Controls die een ander resultaat genereren, zoals het automatisch genereren van datatabellen.

Control Omschrijving

DropDownListMaakt een SELECT-list met size="1". De lijst kan gevuld worden met LISTITEM-Controls of door data binding.

ListBoxMaakt een SELECT-lijst met size="x". De lijst kan gevuld worden met LISTITEM-Controls of door data binding.

CheckBoxListMaakt een HTML-tabel of lijst met HTML-checkboxen. De lijst kan gevuld worden met LISTITEM-Controls of door data binding.

RadioButtonListMaakt een HTML-tabel of lijst met elkaar uitsluitende HTML-radiobuttons. De lijst kan gevuld worden met LISTITEM-Controls of door data binding.

ListItem Is niet echt een control maar wordt gebruikt om bepaalde andere controls te vullen. Deze Control maakt de OPTION-

45

Frank Horemans

Page 46: Cursus ASP.net 1

tags of bv. een nieuwe checkbox in een CheckBoxList Control.

RepeaterHerhaalt bepaalde inhoud voor elk bronelement van een datasource die je hebt ingesteld.

DataListMaakt een HTML-tabel met een rij voor elk bronelement dat je specifiëert.

DataGridMaakt een HTML-tabel voor server-side data binding en heeft ingebouwde functies voor sorteren en manipuleren van de weergegeven rijen.

Achtergrond

De eerste vier Controls uit bovenstaande tabel zijn afgeleid van de klasse ListControl die deel uitmaakt van de namespace System.Web.UI.WebControls en erft uit de klasse WebControl.

Elk van de afzonderlijke Controls vormt een nieuwe klasse met eventueel nieuwe properties en methodes.

Gebruik

De Controls die we hierboven besproken hebben erven uit de klasse System.Web.UI.WebControls.ListControl het event SelectedIndexChanged.

In dit voorbeeld worden de Listbox, Dropdownlist en RadioButtonList samen gebruikt en wordt telkens getoond welke Control werd aangepast. Door de AutoPostBack-property telkens op true te zetten moeten we zelfs niet op een knop drukken.

Met VS.net kan je deze controls op een webpagina slepen en de inhoud bepalen via de eigenschap Items.

De items worden in de code vertaald in ListItem-Controls.

Maak een toepassing met daarin de controls DropDownList1 (België, Nederland, Frankrijk), ListBox1 (Hond, Kat, Paard), RadioButtonList1 (Groen, Rood, Blauw) en een label lblVerander.

Plaats voor de List Controls de eigenschap AutoPostBack op true. Voorzie een event-afhandelingsroutine die het label aanvult wanneer een

verandering gebeurt - bij het event SelectedIndexChanged van de List Controls:

private void Verander(object sender, System.EventArgs e){

46

Frank Horemans

Page 47: Cursus ASP.net 1

ListControl l = (ListControl)sender;lblVerander.Text += "<p><b>Verandering in Control:</b>"

+l.ID+"<br>SelectedIndex: " +l.SelectedIndex+"<br>Tekst: " +l.SelectedItem.Text+"<br>Waarde: " +l.SelectedValue;

}

Voorzie ListBox2 (Jan, Piet, Joris, Corneel, Eric, Denise, Hedwige, Justine, Kim) met:

o AutoPostBack op true o SelectionMode op multiple

Voorzie een event-handler routine voor het afhandelen van een meervoudige selectie:

private void VeranderMeerdere(object sender, System.EventArgs e){

ListControl l = (ListControl)sender;string tekst = "<p><b>Verandering in Control:</b>" +l.ID;foreach(ListItem li in l.Items){

if(li.Selected) tekst += "<br>" +li.Text;}lblVerander.Text += tekst;

}

Voor een ListBox, DropDownList en RadioButtonList kan je een Input Validation Control voorzien, nu wordt de eigenschap SelectedItem.Value gecontroleerd.

De Repeater, DataList en DataGrid komen later aan bod.

5.7 Oefeningen

Toepassing: Jackpot

47

Frank Horemans

Page 48: Cursus ASP.net 1

Maak een online Jackpot-spel.

De gebruiker ziet een jackpot-interface waarbij drie kroontjes worden getoond, de score staat op nul. Wanneer gedrukt wordt op 'speel', dan wordt de jackpot gevuld met drie willekeurige figuren.

punten:

2 gelijk naast elkaar : 20 punten 3 gelijke: 50 punten 3 kroontjes: 100 punten anders: -10 punten

De score wordt na elk spel aangepast volgens de behaalde punten.

Drukken op 'reset' zorgt ervoor dat het spel herbegint: drie kroontjes worden getoond, score staat op nul

Toepassing: Validation Controls

Maak een pagina met volgende tekstvakken:

txtNaam (verplicht) txtNaam2 (zlfde waarde als txtNaam) txtHondVanGertVerhulst (hier moet de gebruiker Samson invullen) txtGeheelGroterDan100 txtGeheelTussen5en10 txtPostnr txtEvenEnGroterDan100

Schik de controls netjes, met bijhorende toelichtingen en validatiecontrols in een tabel.

Zorg steeds voor een controle, zowel client-side als server-side.

Boven het formulier staat de tekst "Gelieve het formulier in te vullen", deze tekst kan veranderen in "Formulier correct ingevuld".

48

Frank Horemans

Page 49: Cursus ASP.net 1

6 ASP.NET : ASP.NET PAGINA'S IN DETAIL

1. Inleiding 2. Een pagina uitvoeren 3. System.Web.UI.Page: overzicht 4. De eigenschap Request 5. De eigenschap Response 6. De eigenschap IsPostBack 7. De eigenschap Context 8. De eigenschap Server 9. Page Directives

6.1 Inleiding

Je hebt reeds kennis gemaakt met formulieren en ook met een aantal basisfunctionaliteiten van de System.Web.UI.Page-klasse, de klasse waarvan elke webpagina een object vormt wanneer die uitgevoerd wordt. In dit hoofdstuk gaan we dieper op deze klasse in.

6.2 Een ASP.Net pagina uitvoeren

Compilatie

ASP.net pagina's worden dynamisch gecompileerd wanneer ze de eerste keer worden opgevraagd. Dit gebeurt in een WebServer (IIS) in de context van een Web applicatie. Dynamische compilatie is niet specifiek voor ASP.net pagina's (.aspx), maar geldt ook voor .Net Web Services (.asmx), Web User Controls (.ascx), HTTP handlers (.ashx), een nog een aantal, zoals global.asax (meer hierover later). Een pipeline van modules zorgt ervoor dat de code die je hebt geschreven voor het maken van een ASP.Net webpagina evolueert naar een ASP.Net object, meer bepaald een instantie van een klasse afgeleid van de Page klasse. De ASP.NET HTTP runtime verwerkt het Page-object en zorgt ervoor dat het de opmaak genereert als response naar de browser. Dit opmaken van de response gebeurt in een cyclus die we de levenscyclus (life cycle) van de pagina noemen.

6.3 System.Web.UI.Page: overzicht

ASP.net pagina's uitvoeren

Wanneer een browser een ASP.NET pagina opvraagt herkent IIS de aspx-extensie en laat de ASP.NET module aspnet_isapi.dll de vraag verder afhandelen. De aspnet_isapi.dll plaatst het aspx-bestand in een nieuwe klasse-definitie in de namespace ASP. Mijnpagina.aspx wordt een ASP.mijnpagina_aspx klasse. Deze klasse erft van de Page klasse uit de System.Web.UI namespace. Elke ASP.NET webpagina die wordt opgevraagd, wordt in feite gecompileerd tot een klasse die erft van de .NET Page-klasse en dus alle functionaliteit van deze klasse kan gebruiken.

Events bij het uitvoeren van ASP.net pagina's

ASP.NET is event-driven: code wordt uitgevoerd wanneer bepaalde acties worden ondernomen. Deze acties worden gestart door een gebruiker of automatisch binnen het .NET Framework.

49

Frank Horemans

Page 50: Cursus ASP.net 1

De volgorde waarin events uitgevoerd worden bij het laden van elke pagina noemen we de life cycle:

Event Omschrijving

Page Setup

Hier wordt een tree van controls opgebouwd en gedetecteerd waarom de pagina moet uitgevoerd worden: een normaal request, een postback, een cross-page postback of een callback. De collectie gegevens ontvangen via POST of GET wordt voorbereid. Na deze stap kunnen we op events sturen naar de eventhandlers in de broncode.

PreInit

Geïntroduceerd in ASP.Net 2.0: het beginpunt in de levenscyclus van een pagina. Wanneer dit event wordt uitgevoerd zijn nog geen masterpage of theme geassocieerd. De scroll-positie is gekend, geposte data is beschikbaar en de controls werden geïnitialiseerd met de eigenschappen zoals opgegeven in de aspx-broncode. Controls hebben geen ID als dit niet in de aspx-code is opgegeven. Masterpage of theme opgeven is vanaf nu mogelijk via code. IsPostBack, IsCrossPagePostBack en IsCallBack worden hier ingesteld.

InitMasterpage en theme zijn ingesteld en kunnen niet meer worden veranderd. Alle child controls zien hun OnInit methode uitgevoerd. De ViewState is nog niet herzet.

InitCompleteGeïntroduceerd in ASP.Net 2.0: controls halen hun ViewState op. Alles wat voor dit event in de ViewState geschreven is zal verloren gaan bij de volgende PostBack

PreLoad

Geïntroduceerd in ASP.Net 2.0: enkel voor pagina's: aangeven dat de pagina de systeemniveau-initialisatie heeft voleindigd en nu de aandacht kan geschonken worden aan de gebruikerscode

Page_Load Eerst uitgevoerd voor de pagina, daarna voor alle controls. Wanneer de pagina geladen is, de __Viewstate is nu volledig geladen en kan zonder probleem benaderd

50

Frank Horemans

Page 51: Cursus ASP.net 1

worden.

PostBack afhandelen

Het PostBack-mechanisme is het hart van ASP.Net programmeren. Het bestaat uit het versturen van formuliergegevens naar dezelfde pagina en het gebruiken van de viewstate om de oproepcontext te construeren.

Control EventWanneer een control een event heeft geraised, zoals wanneer een druk op een knop de pagina heeft herladen

LoadCompleteGeïntroduceerd in ASP.Net 2.0: enkel voor de pagina: duidt het einde aan van de paginavoorbereidingsfase, hierna wordt de pagina afgewerkt: Page Rendering

Pagina-afwerking De pagina is klaar om output naar de browser te sturen

PreRenderPagina's en Controls kunnen hier updates ondergaan vooraleer de output wordt gegenereerd

PreRenderCompleteGeïntroduceerd in ASP.Net 2.0: geeft aan dat de PreRender-fase voor alle controls voleindigd is

SaveStateCompleteDe nieuwe toestand van de controls wordt opgeslagen in de viewstate

Page_UnloadWanneer de pagina uit het server-geheugen wordt gehaald, eerst voor alle controls, daarna voor de pagina.

6.4 De eigenschap Request

Wanneer een browser een request voor een pagina geeft, wordt de informatie die de browser naar de server stuurt netjes door het .NET Framework gebundeld in een HttpRequest. Dit object kan je vanuit de Page-klasse aanspreken met de eigenschap Request.

De request informatie kan je gebruiken om informatie te weten over de browser, cookie-informatie op te vragen,...

51

Frank Horemans

Page 52: Cursus ASP.net 1

6.5 De eigenschap Response

Het Page-object dat we maken door een aspx-pagina op te vragen heeft een eigenschap Response. Deze eigenschap bevat in feite een object van de klasse HttpResponse. Dit object heeft een aantal interessante methoden en eigenschappen:

Redirect: de browser naar een andere pagina sturen - de formulierinformatie wordt NIET meegestuurd

Response.redirect("http://www.ivobrugge.be");

Write: tekstgegevens naar de browser sturen

6.6 De eigenschap IsPostBack

Deze eigenschap van de klasse Page bevat een Boolean waarde die aangeeft of de pagina werd teruggepost naar de server. Hiermee kan je controleren of een pagina voor het eerst wordt getoond of er reeds een terugpost naar de server is geweest doordat de gebruiker bv. op een knop heeft gedrukt. Deze eigenschap zal in de rest van de cursus vaak worden gebruikt.

Voorbeeld

In dit voorbeeld wordt een ArrayList gebruikt om een ListBox te vullen. We zorgen er voor dat deze ArrayList slechts één keer gebruikt wordt om de ListBox te vullen : de eerste keer dat de pagina wordt getoond. Wanneer de gebruiker de pagina verstuurd gebreurt een postback, de formulierelementen behouden hun 'state' door het verborgen Viewstate - formulierveld. Hierdoor hoef je de ArrayList geen tweede keer te gebruiken.

Deze techniek zal vaak aangewend worden wanneer keuzelijsten e.d. gevuld worden met gegevens uit een database. Zo is er slechts één keer een dataconnectie nodig.

52

Frank Horemans

Page 53: Cursus ASP.net 1

IsPostback.aspx...<form id="form1" runat="server"><div> <asp:ListBox ID="LBdieren" runat="server" AutoPostBack="True"></asp:ListBox> <br /> <br /> <asp:Label ID="LblKeuze" runat="server" Text="Label"></asp:Label></div></form>...

IsPostback.aspx.cs...

protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { ArrayList dieren = new ArrayList(); dieren.Add("Kat"); dieren.Add("Hond"); dieren.Add("Aap"); dieren.Add("Ezel"); dieren.Add("Giraf");

dieren.Sort();

LBdieren.DataSource = dieren; LBdieren.DataBind(); } else { LblKeuze.Text = "Je koos een " + LBdieren.SelectedItem.Text; }

}

6.7 De eigenschap Context

De eigenschap Context bevat alle http-informatie aangaande een http-request. De eigenschap Context bevat een instantie van de klasse System.Web.HttpContext. Dit object heeft een aantal interessante members.

De eigenschap Context kan je gebruiken om informatie bij te houden wanneer de gebruiker naar een andere pagina wordt gestuurd. Niets is vervelender voor jouw als programmeur en voor de gebruiker dat dezelfde informatie meermaals moet worden verstrekt.

member omschrijving

53

Frank Horemans

Page 54: Cursus ASP.net 1

SessionBevat een HttpSessionState-object waarmee je informatie van een bepaalde gebruiker (sessie) kan bewaren. Je kan de informatie per gebruiken in key/value paren.

Application evat een HttpApplicationState-object waarmee je informatie voor alle gerbuikers kan bewaren. Je kan de informatie in key/value paren opslaan.

Items

Collectie met key/value paren die informatie bewaren van alle componenten die deelnemen in één http-request. Deze collectie is dus slechts gekend gedurende één request van de gebruiker. Met Server.Transfer kan je de gegevens wel meegeven. Klikt de gebruiker echter op een hyperlink of ga je met Response.Redirect naar een andere pagina van de site, dan gaat deze informatie verloren.

Handler Levert je informatie over de pagina die opgevraagd wordt, maar stelt je ook in staat om informatie over de aanvrager op te vragen na bijvoorbeeld Server.Transfer

TraceGeeft je de mogelijkheid het uitvoeren van je toepassing te traceren en te zien waar 'bottlenecks' zich bevinden

In het bestand Global.asax kan je code schrijven voor onder meer volgende event-handlers:

event-handler omschrijving

Application_Start

Wordt uitgevoerd wanneer de applicatie wordt opgestart: onze toepassing voorbereiden op het ontvangen van requests, zoals databaseconnecties openen, applicatievariabelen instellen, ...

Session_StartWanneer een sessie start: een gebruiker betreedt de site

54

Frank Horemans

Page 55: Cursus ASP.net 1

Session_End Een gebruiker verlaat de toepassing

Application_End De applicatie wordt afgesloten

Application_BeginRequest Bij elke request

Application_EndRequest Na elk request

Application_Error Afhandelen van onverwachte fouten

Het bestand Global.asax moet zich in de root van de virtuele map in IIS bevinden.

Voorbeeldtoepassing

We maken een kleine toepassing die het werken met contextitems, sessievariabelen en applicatievariabelen demonstreert.

We maken een aspx pagina waarin we in het Load-event van het formulier een contextitem-, twee sessievariabelen en een applicatievariabele vullen.

We voorzien ook twee knoppen, bij het klikken op een knop wordt de gebruiker doorgestuurd naar een andere pagina. Het doorsturen gebeurt een keer met Response.Redirect en een keer met Server.Transfer (zie volgend onderdeel in de cursus).

Op de tweede pagina’s plaatsen we vier labels die de inhoud van deze variabelen moeten tonen. We gaan telkens na of er een fout optreedt.

Met Server.Transfer

55

Frank Horemans

Page 56: Cursus ASP.net 1

Met Response.Write

Content.aspx<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Context.aspx.cs" Inherits="Context" %>

<!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> <table id="Table1" cellspacing="1" cellpadding="1" width="440" border="1" style="WIDTH: 440px; HEIGHT: 124px">

<tr><td style="WIDTH: 102px">Items</td><td>item1</td><td><asp:Label id="Label1" runat="server" Width="158px" BorderStyle="Solid" BorderWidth="1px" BackColor="#C0FFC0" ForeColor="Maroon"></asp:Label></td></tr>

<tr><td style="WIDTH: 102px">Session</td><td>sessie1</td><td><asp:Label id="Label2" runat="server"Width="156px" BorderStyle="Solid" BorderWidth="1px"BackColor="#C0FFC0" ForeColor="Maroon"></asp:Label></td></tr>

<tr><td style="WIDTH: 102px">Application</td><td>app1</td><td><asp:Label id="Label3" runat="server"Width="156px" BorderStyle="Solid" BorderWidth="1px"BackColor="#C0FFC0" ForeColor="Maroon"></asp:Label></td></tr>

<tr><td style="WIDTH: 102px">Session 2</td><td>lijstitem</td><td><asp:Label id="Label4" runat="server"Width="156px" BorderStyle="Solid" BorderWidth="1px"BackColor="#C0FFC0" ForeColor="Maroon"></asp:Label></td>

</tr>

56

Frank Horemans

Page 57: Cursus ASP.net 1

</table><p><asp:Button id="btnLaadTweede" runat="server" Text="Transfer"OnClick="btnLaadTweede_Click"></asp:Button><asp:Button id="btnRedirect" runat="server" Text="Redirect"OnClick="btnRedirect_Click"></asp:Button></p>

</div></form></body></html>

Context.aspx.csprivate void Page_Load(object sender, System.EventArgs e)

{Context.Items["item1"] = "Inhoud item1";Context.Session["sessie1"] = "Inhoud sessie1";Context.Application["app1"] = "Inhoud app1";

ArrayList lijst = new ArrayList();lijst.Add("aap");lijst.Add("hond");lijst.Add("kat");

Context.Session["lijst"] = lijst;

Label1.Text = Context.Items["item1"].ToString();Label2.Text = Context.Session["sessie1"].ToString();Label3.Text = Context.Application["app1"].ToString();Label4.Text = lijst[1].ToString();

}

private void btnLaadTweede_Click(object sender, System.EventArgs e){

Server.Transfer("Context_deel2.aspx");}

private void btnRedirect_Click(object sender, System.EventArgs e){

Response.Redirect("Context_deel2.aspx");}

Context_deel2.aspx<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Context_deel2.aspx.cs" Inherits="Context_deel2" %>

<!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>Context: tweede pagina</title></head><body> <form id="form1" runat="server"> <div> <table id="Table1" style="WIDTH: 440px; HEIGHT: 124px"

cellspacing="1" cellpadding="1" width="440" border="1"><tr>

<td style="WIDTH: 102px">Items</td><td>item1</td><td><asp:Label id="Label1" runat="server"

57

Frank Horemans

Page 58: Cursus ASP.net 1

ForeColor="Maroon" BackColor="#C0FFC0" BorderWidth="1px" BorderStyle="Solid" Width="158px"></asp:Label></td></tr>

<tr><td style="WIDTH: 102px">Session</td><td>sessie1</td><td><asp:Label id="Label2" runat="server" ForeColor="Maroon" BackColor="#C0FFC0"BorderWidth="1px" BorderStyle="Solid" Width="156px"></asp:Label></td></tr>

<tr><td style="WIDTH: 102px">Application</td><td>app1</td><td><asp:Label id="Label3" runat="server"ForeColor="Maroon" BackColor="#C0FFC0"BorderWidth="1px" BorderStyle="Solid" Width="156px"></asp:Label></td></tr>

<tr><td style="WIDTH: 102px">Session 2</td><td>lijstitem</td><td><asp:Label id="Label4" runat="server"ForeColor="Maroon" BackColor="#C0FFC0"BorderWidth="1px" BorderStyle="Solid" Width="156px"></asp:Label></td></tr>

</table> </div> </form></body></html>

Context_deel2.aspx.csprivate void Page_Load(object sender, System.EventArgs e)

{try

{Label1.Text = Context.Items["item1"].ToString();}catch(Exception ex){Label1.Text = "Fout: " +ex.Message;}

try{Label2.Text = Context.Session["sessie1"].ToString();}catch(Exception ex){Label2.Text = "Fout: " +ex.Message;}

try{Label3.Text =Context.Application["app1"].ToString();}catch(Exception ex){Label3.Text = "Fout: " +ex.Message;}

try{

58

Frank Horemans

Page 59: Cursus ASP.net 1

ArrayList l = (ArrayList)Context.Session["lijst"];Label4.Text = l[2].ToString();}catch(Exception ex){Label3.Text = "Fout: " +ex.Message;}

}

Je merkt dat bij het versturen met Response.Write de informatie in contextitems niet meer wordt onthouden.

Uit deze toepassing valt het verschil tussen sessie- en applicatievariabelen niet uit te maken. Onthoud dat sessievariabelen een set variabelen vormen voor elke individuele user, applicatievariabelen vormen een set gemeenschappelijke variabelen voor alle gebruikers.

6.8 De eigenschap Server

De eigenschap Server van de klasse Page bevat een object van de klasse System.Web.HttpServerUtility waarmee je toegang hebt tot een arsenaal aan interessante eigenschappen en methodes om de webserver te manipuleren.

member Omschrijving

MapPathRetourneert het fysieke pad op de server van de huidige virtuele map. Kan handig gebruikt worden voor het openen en opslaan van bestanden op de server

HtmlEncode Encodeert een string voor weergave in een browser

Transfer

Beëindigt de uitvoering van de huidige pagina en begint de uitvoering van een andere pagina. In tegenstelling tot bij Response.Write kan je na een transfer wel nog aan de elementen van de bronpagina!

ExecuteVoer een andere pagina uit en ontvang eventueel de gegenereerde output in de huidige pagina

MachineName Retourneert de naam van de servercomputer

59

Frank Horemans

Page 60: Cursus ASP.net 1

Voorbeeldtoepassing

In deze toepassing leer je hoe je na een Transfer aan de gegevens van de bronpagina kan opvragen. Je maakt ook kennis met de methode Execute.

Maak een pagina met daarin een TextBox en een Button. Voorzie in de codebehind-file een property Voornaam.

Bij klikken op de knop voorzie je dat de gebruiker met Server.Transfer wordt doorgestuurd naar een tweede pagina.

Op de tweede pagina kunnen we de inhoud van de TextBox en de waarde van de Property van de eerste pagina opvragen! Daarvoor gebruiken we de eigenschap Handler van de Context (HttpContext) van de pagina. De ontvangen gegevens typecasten we naar de klasse van de originele pagina. Een control kunnen we nu vinden met de methode FindControl Een property kunnen we rechtstreeks aanspreken

De methode Execute staat je toe een externe pagina uit te voeren. Deze pagina kan uitvoercommando's bevatten (controles, wegschrijven in een database, ...), je kan met behulp van een TextWriter ook eventuele respons-informatie van de uitgevoerde pagina opvangen. We geven de opgevraagde waarde weer met behulp van drie Labels.

ServerMethoden.aspx<asp:TextBox ID="Txtinvul" runat="server"

></asp:TextBox><asp:Button ID="BtnVerstuur" runat="server"

OnClick="BtnVerstuur_Click" Text="Button" />

ServerMethdoden.aspx.cspublic string Voornaam{ get { return "William"; }}

protected void Page_Load(object sender, EventArgs e){}

protected void BtnVerstuur_Click(object sender, EventArgs e){ Server.Transfer("ServerMethoden_deel2.aspx");}

ServerMethoden_deel2.aspx<asp:Label ID="LblControl" runat="server" Text="Label"></asp:Label><br /><asp:Label ID="LblProperty" runat="server" Text="Label"></asp:Label>

60

Frank Horemans

Page 61: Cursus ASP.net 1

<br /><asp:Label ID="LblExecute" runat="server" Text="Label"></asp:Label>

ServerMethoden_deel2.aspx.csprotected void Page_Load(object sender, EventArgs e){ ServerMethoden origineel = (ServerMethoden)Context.Handler; LblControl.Text = ((TextBox)origineel.FindControl("TxtInvul")).Text; LblProperty.Text = origineel.Voornaam;

StringWriter sw = new StringWriter(); Server.Execute("ServerMethoden_uitvoeren.aspx", sw); LblExecute.Text = sw.ToString();}

ServerMethoden_uitvoeren.aspx<%= "Commando's zijn uitgevoerd ! " %>

6.9 Page Directives

Wanneer een pagina gemaakt wordt kan je een aantal attributen opnemen in deze pagina. Deze attributen kan je instellen via directives. Een aantal hiervan komen later in de cursus meer in detail aan bod.

Directive Beschrijving

@AssemblyHiermee kan je een assembly in je pagina importeren (.dll-bestand)

@Control Definieert een attribuut specifiek voor een control

@Implements

Stelt je in staat een interface in je webpagina te importeren. Hierdoor geef je aan dat je webpagina de in een interface gedefiniëerde eigenschappen, methoden en events zal gebruiken

@Import

Hiermee kan je een namespace importeren in de pagina. Dit zorgt ervoor dat alle klassen en interfaces binnen die namespace bruikbaar zijn binnen de pagina. Het .NET Framework importeert standaar een heel aantal namespaces voor jou

@Master Identificeert een Master Page (niet beschikbaar in .Net 1.1)

61

Frank Horemans

Page 62: Cursus ASP.net 1

@OutputcacheHiermee kan je instellen hoe de pagian gecached wordt op de server

@PageEen derictive die we al vaak hebben gebruikt is de @Page directive. Hiermee hebben we een attribuut language ingesteld om aan te geven welke .NET taal we wensen te gebruiken

@ReferenceWordt gebruikt om een pagina of user control in de pagina te importeren. Op deze manier wordt de pagina of usrer control runtime gelilnked

@RegisterHiermee kan je server controls die je eventueel zelf hebt ontworpen in de pagina importeren met een specifieke tag (prefix en naam)

62

Frank Horemans

Page 63: Cursus ASP.net 1

7 ASP.NET : PAGINA COMPOSITIE

1. Inleiding 2. Master Pages 3. Themes 4. Wizards

7.1 Inleiding

Op je website wens je wellicht dat je pagina's allemaal dezelfde 'look and feel' hebben: ze delen hetzelfde uiterlijk. Figuren worden gemeenschappelijk gebruikt, User Interface elementen, menu's en zoekformulieren komen telkens terug.

Je mogelijkheid is het werken met User Controls, en een referentie naar deze controls leggen op elke pagina. In grote projecten verzeil je met deze aanpak dikwijls in een chaotisch, moeilijk te onderhouden model.

ASP.net 2.0 beschikt over een aantal elementen die het voor de ontwikkelaar bijzonder aangenaam maken om consistente webpagina's te maken.

ASP.Net 2.0 element

Beschrijving

MasterpagesDe mogelijkheid oom jouw pagina in te passen in een welbepaald sjabloon of template

ThemesMet themes kan je op een eenvoudige manier de volledige site een consistente gebruikersinterface geven. Themes zijn gebouwd op CSS-technologie.

WizardsEen meerstapsprocedure waarbij de gebruiker op een eenvoudige en logische manier formulieren kan invullen

7.2 Masterpages

Een masterpage in ASP.Net is een apart bestand waar je naar kan verwijzen vanuit een gewone ASP.Net pagina. Op deze masterpage kan je regio's aanduiden waar een andere pagina inhoud kan plaatsen. Deze regio's worden gemarkeerd met de PlaceHolder control.

Een masterpage maken

Een masterpage wordt gekenmerkt door de @Master directive.

63

Frank Horemans

Page 64: Cursus ASP.net 1

Om met Visual Studio 2005 een masterpage te maken voeg je een nieuw item toe van het type Master Page. Je merkt dat de extensie van deze file geen .aspx wordt, maar .master

Op de masterpage vind je standaard 1 ContenPlaceHolder: deze markeert de plaats waar vanuit een andere pagina inhoud kan worden opgegeven

Je kan nu de masterpage verder opmaken met controls die je op elke pagina wil terugvinden

Je kan nog ContentPlaceHolders toevoegen als er meerder gebieden zijn die opgevuld dienen te worden door de subpagina, in de subpagina kan je dan voor elke ContentPlaceHolder een Content-control invoegen

Je kan de ContenPlaceHolder-controls inhoud geven voor het geval ze op een subpagina niet ingevuld worden (standaardinhoud)

Een inhoudspagina maken

Voeg een nieuw item toe aan de Web Site: Web Form Selecteer de optie 'Select Master Page', druk OK Kies je masterpage De inhoudspagina krijgt automatisch de Content-controls voor de respectievelijke

ContentPlaceHolders in de MasterPage

Meester.master<%@ Master Language="C#" AutoEventWireup="true" CodeFile="Meester.master.cs" Inherits="Meester" %>

<!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>Welkom op deze site</title></head><body> <form id="form1" runat="server"> <div> <div style="font-size: 2em; color: #cc6633; font-family: Rockwell"> Werken met masterpages</div> <br /> <br /> <asp:contentplaceholder id="Inhoud" runat="server"> standaardinhoud </asp:contentplaceholder> </div> </form>

64

Frank Horemans

Page 65: Cursus ASP.net 1

</body></html>

Inhoudspagina.aspx<%@ Page Language="C#" MasterPageFile="~/Meester.master"

AutoEventWireup="true" CodeFile="Inhoudspagina1.aspx.cs"Inherits="Inhoudspagina1" Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="Inhoud" Runat="Server">Inhoud vanuit de eerste inhoudpagina</asp:Content>

Titel instellen

Standaard krijgt de pagina de titel zoals aangegeven door de tag title in de masterpage. Je kan vanuit de subpagina's de titel instellen met behulp van het attribuut Title in de @Page-directive.

<%@ Page Language="C#" MasterPageFile="~/Meester.master" AutoEventWireup="true" CodeFile="Inhoudspagina1.aspx.cs" Inherits="Inhoudspagina1" Title="hallo iedereen" %>

Masterpages nesten

Je kan een masterpage ook als inhoudspagina van een andere masterpage instellen. Deze child-masterpage bevat dan Content-controls voor de ContentPlaceHolder in de hooft-masterpage.

Binnen de Content-controls van de child-masterpage kan je dan weer ContentPlaceHolders plaatsen voor opvulling door gewone pagina's (of opnieuw een child-masterpage natuurlijk).

Met VS.Net 2005 kan je dit niet via de IDE-opties regelen, je kan voor een masterpage geen andere masterpage selecteren. Oplossing: je maakt de child-masterpage als gewone Web Form en verandert de directive bovenaan van @Page in @Master en verwijdert het Title-attribuut. Verander nu ook de basisklasse in die van de masterpage.

7.3 Themes

Inleiding

Bij het maken van een webapplicatie ben je in eerste instantie bekommerd over de correcte werking, maar is het ook aangenaam dat je site er mooi uitziet.

Voor het opmaken van elementen op een pagina gebruik je wellicht reeds CSS-bestanden.

ASP.Net thema's kan je goed vergelijken met Windows XP thema's: je kan elementen heel eenvoudig een ander uiterlijk geven. Het instellen van een ASP.Net thema is even eenvoudig als het instellen van een eigenschap.

65

Frank Horemans

Page 66: Cursus ASP.net 1

Om ASP.Net thema's te gebruiken heb je CSS-bestanden nodig, maar dit is niet voldoende.

Wat is een theme

Een theme is een set van skins en gerelateerde bestanden zoals Style Sheets en figuren: een soort van Super Style Sheet.

Term Definitie

SkinEen benoemde set van eigenschappen en templates die kan toegepast worden op een of meer controls op een pagina. Een skin wordt steeds geassocieerd met een controltype.

Style SheetEen CSS of server-side style sheet bestand dat kan gebruikt worden door je pagina's

Stylesheet Theme

Een theme dat gebruikt wordt om eigenschappen van controls op te maken. De control kan de theme nog overriden.

Custumization theme

Een theme dat gebruikt wordt om eigenschappen van controls op te maken. Het theme overrides de control en elk stylesheet theme. De term theme zal in het vervolg van de cursus gebruikt wordt voor een Customization theme.

Structuur van een theme

Themes vormen een verzameling van verschillende bestanden en mappen onder een gemeenschappelijke root-directory:

%Windows%\Microsoft.NET\Framework\[versie]\ASP.NETClientFiles\Themes

Lokale themes worden gemaakt in de App_Themes map van de huidige applicatie.

Volgende bestanden kunnen een theme uitmaken:

Bestand Beschrijving

CSS Style Sheet

Skin Theme-specifieke opmaak voor een bepaalde control

66

Frank Horemans

Page 67: Cursus ASP.net 1

FigurenFiguren gebruikt in bepaalde themes, standaard geplaatst in een submap images onder de themamap

Templates Template-definities voor templatable controls (zoals bv. DataGrid)

Een theme maken

De bestanden voor een theme plaats je in een submap van de App_Theme map van je Web Site.

Rechtsklik je Web Site, kies add ASP.NET folder, themes De App_Theme map wordt gemaakt samen met een eerste submap, geef die de naam

sober Voeg een item toe aan de map sober: Skin file: Sober.skin

<asp:BulletedList runat="server" BulletImageUrl="images/blad.png" BulletStyle="CustomImage" Font-Names="Verdana" ForeColor="Gray" />

Voeg een New Folder toe aan de map sober: images Kopiëer hierin volgende figuur: blad.png

Voeg een item toe aan de map sober: Style Sheet: Sober.css

body{

background-color: #ffccff;}

Voeg een Web Form toe: ThemeGebruiken.aspx

<%@ Page Language="C#" Theme="sober" ......<asp:BulletedList ID="BulletedList1" runat="server"> <asp:ListItem>Eerste item</asp:ListItem> <asp:ListItem>Tweede item</asp:ListItem> <asp:ListItem>Derde Item</asp:ListItem></asp:BulletedList>...

Voer de pagina uit

67

Frank Horemans

Page 68: Cursus ASP.net 1

Maak nog een tweede theme (rechtsklik App_Themes > Add ASP.Net folder > Theme): vrolijk

Zorg voor een skin file:

<asp:BulletedList runat="server" BulletImageUrl="images/boekje.gif" BulletStyle="CustomImage" Font-Names="Bookman old style" ForeColor="Purple" />

Maak een submap images, kopiëer: boekje.gif Zorg voor een css-file:

body{

background-color: #ffff66;}

Pas het Theme-attribuut op de aspx-pagina aan naar vrolijk

Themes dynamisch laden

We passen de pagina ThemeGebruiken.aspx aan zodat de gebruiker zelf kan kiezen welk theme wordt toegepast.

Voorzie een DropDownList:

Kies een theme:<asp:DropDownList ID="DDLtheme" runat="server" AutoPostBack="True"></asp:DropDownList><br />

Voorzie in de codebehind ThemeGebruiken.aspx.cs:

...using System.IO;

68

Frank Horemans

Page 69: Cursus ASP.net 1

...

protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { //themalijst ophalen bij eerste request, DDLtheme.DataSource = GetThemeLijst(); DDLtheme.DataBind();

//plaats de keuzelijst op de tekstwaarde van attribuut Theme DDLtheme.Text = this.Theme.ToString(); }

}

void Page_PreInit(object sender, EventArgs e) { string theme = ""; if (Page.Request.Form.Count > 0) theme = Page.Request["DDLtheme"].ToString(); if (theme != "") this.Theme = theme; }

protected ArrayList GetThemeLijst() { string path = Request.PhysicalApplicationPath + @"App_Themes"; DirectoryInfo dir = new DirectoryInfo(path); ArrayList themas = new ArrayList(); foreach (DirectoryInfo di in dir.GetDirectories()) { themas.Add(di.Name); }

return themas; }

7.4 Wizards

Wat is een Wizard?

Een Wizard Component staat je toe om stap-voor-stap informatie aan de gebruiker te vragen. Een Wizard is conceptueel behoorlijk simpel, maar om dit te implementeren over het statusloze http-protocol kan behoorlijk lastig zijn. Gelukkig is er nu sinds ASP.Net 2.0 de Wizard-control.

Een Wizard ondersteund lineaire en niet-lineaire nagigatie: het staat je toe terug te keren of stappen over te slaan die onnodig zijn in de huidige context. De Wizard control ondersteund themes, stijlen en templates.

De Wizard is een samengestelde control en maakt automatisch een aantal communicerende controls aan zoals navigatieknoppen en Panels. De control garandeert ook dat de state behouden blijft, al ga je vooruit of achteruit in de navigatie.

69

Frank Horemans

Page 70: Cursus ASP.net 1

Structuur van een Wizard

Een Wizard bestaat uit vier delen: Header, View, Navigation bar en Sidebar.

Een Wizard aanmaken

Sleep op een nieuwe Web Form een Wizard uit de Toolbox Met Auto Format kies je een voorgedefiniëerde opmaak: Classic Via de eigenschappen van de Wizard kan je de knopteksten voor next, previous, ...

aanpassen Via Add/Remove Wizardsteps kan je stappen toevoegen aan de Wizard Zorg voor een eerste stap van het steptype Start (geen previous knop)

o Zet de StartNextButtonText op Beginneno In het View-gebied kan je nu zelf inhoud opgeven

Gebruik je fantasie en maak een mooie Wizard...

70

Frank Horemans

Page 71: Cursus ASP.net 1

WizardGebruiken.aspx<%@ Page Language="C#" AutoEventWireup="true" CodeFile="WizardGebruiken.aspx.cs" Inherits="WizardGebruiken" %>

<!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> <asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0" BackColor="#EFF3FB" BorderColor="#B5C7DE" BorderWidth="1px" CancelButtonText="Annuleren" FinishCompleteButtonText="Voltooien" FinishPreviousButtonText="Vorige" Font-Names="Verdana" Font-Size="0.8em" Height="294px" StartNextButtonText="Beginnen" StepNextButtonText="Volgende" Width="439px" OnFinishButtonClick="Wizard1_FinishButtonClick"> <WizardSteps> <asp:WizardStep runat="server" StepType="Start" Title="Welkom"> <strong><span style="font-size: 1.4em">Welkom in de <br /> persoonsregistratie- Wizard</span></strong></asp:WizardStep> <asp:WizardStep runat="server" Title="Naam"> <table> <tr> <td style="text-align: left"> <asp:Label ID="Label1" runat="server" Font-Bold="True" Text="Voornaam"></asp:Label> </td> <td>

71

Frank Horemans

Page 72: Cursus ASP.net 1

<asp:TextBox ID="TxtVoornaam" runat="server"></asp:TextBox> </td> </tr> <tr> <td style="text-align: left"> <asp:Label ID="Label2" runat="server" Font-Bold="True" Text="Naam"></asp:Label> </td> <td> <asp:TextBox ID="TxtNaam" runat="server"></asp:TextBox> </td> </tr> </table>     </asp:WizardStep> <asp:WizardStep runat="server" Title="Woonplaats">  <table> <tr> <td style="text-align: left"> <asp:Label ID="Label3" runat="server" Font-Bold="True" Text="Provincie"></asp:Label> </td> <td>  <asp:DropDownList ID="DDLprovincie" runat="server"> <asp:ListItem>Antwerpen</asp:ListItem> <asp:ListItem>Limburg</asp:ListItem> <asp:ListItem>Oost-Vlaanderen</asp:ListItem> <asp:ListItem>Vlaams-Brabant</asp:ListItem> <asp:ListItem>West-Vlaanderen</asp:ListItem> </asp:DropDownList> </td> </tr> <tr> <td style="text-align: left"> <asp:Label ID="Label4" runat="server" Font-Bold="True" Text="Postcode"></asp:Label> </td> <td> <asp:TextBox ID="TxtPostcode" runat="server"></asp:TextBox> </td> </tr> </table> </asp:WizardStep> <asp:WizardStep runat="server" StepType="Finish" Title="Leeftijd"> <asp:Label ID="Label5" runat="server" Text="Leeftijd:"></asp:Label> <asp:TextBox ID="TxtLeeftijd" runat="server"></asp:TextBox> </asp:WizardStep> <asp:WizardStep runat="server" StepType="Complete" Title="Voltooid">

72

Frank Horemans

Page 73: Cursus ASP.net 1

Dank u voor het invullen van de gegevens:<br /> <br /> <asp:Label ID="LblRes" runat="server" Text="Label"></asp:Label> <br /> </asp:WizardStep> </WizardSteps> <StepStyle Font-Size="0.8em" ForeColor="#333333" /> <SideBarStyle BackColor="#507CD1" Font-Size="0.9em" VerticalAlign="Top" /> <NavigationButtonStyle BackColor="White" BorderColor="#507CD1" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#284E98" /> <SideBarButtonStyle BackColor="#507CD1" Font-Names="Verdana" ForeColor="White" /> <HeaderStyle BackColor="#284E98" BorderColor="#EFF3FB" BorderStyle="Solid" BorderWidth="2px" Font-Bold="True" Font-Size="0.9em" ForeColor="White" HorizontalAlign="Center" /> </asp:Wizard> </div> </form></body></html>

WizardGebruiken.aspx.cs

using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;

public partial class WizardGebruiken : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) {

} protected void Wizard1_FinishButtonClick(object sender, WizardNavigationEventArgs e) { LblRes.Text = "Bedankt voor uw registratie " + TxtVoornaam.Text + " " + TxtNaam.Text + " (" + TxtLeeftijd.Text + ")<p>" + "U komt uit " + DDLprovincie.Text + ", uw postcode is " + TxtPostcode.Text; }}

73

Frank Horemans

Page 74: Cursus ASP.net 1

8 ASP.NET : USER CONTROLS

1. User Controls 2. Custom Controls 3. Composite Controls 4. Oefeningen

8.1 User Controls

Wat zijn User Controls

Als .Net ontwikkelaar kan je de Web Controls uitbreiden met je eigen controls: User Controls. Deze User Controls vormen herbruikbare componenten. Je kan ze in een Web Form Application gebruiken precies zoals de gewone controls.

Het aanroepen van Controls in .Net kent volgende fasen:

Initialiseren Laad Viewstate Postback data verwerken Load PostBack veranderingen waarnemen Postback events afhandelen Prerender status opslaan Render Dispose Unload

User Controls aanmaken: Kalender.ascx

Met Visual Studio .net kan je op een eenvoudige manier User Controls in een project aanmaken:

Start een nieuwe Web Site: Controls Kies Project > add Web User Control: Kalender.ascx

Een User control vormt een grafische component die je in een Web Form kan gebruiken, een User Control kan je echter niet zelfstandig uitvoeren. Vandaar dat User Controls een andere extensie hebben: ascx in plaats van aspx. Een User Control (.ascx) kan je in Visual Studio.net heel eenvoudig op de pagina slepen.

Maak volgende lay-out in de Web Form Default.aspx:

74

Frank Horemans

Page 75: Cursus ASP.net 1

Default.aspx<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Src="Kalender.ascx" TagName="Kalender" TagPrefix="uc1" %>

<!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> <table> <tr> <td valign="top"> Geboortedatum:</td> <td> <uc1:Kalender ID="Kalender1" runat="server" /> </td> </tr> <tr> <td valign="top"> Datum in dienst:</td> <td> <uc1:Kalender ID="Kalender2" runat="server" /> </td> </tr> </table> </div> </form></body></html>

De Page directive Register wordt gebruikt om een control te registeren op een webpagina. Nu kan je zoveel instanties van de Control Kalender op de Web Form gebruiken als je wil.

Pas nu de Kalender.ascx - file aan (design of HTML-view naar keuze): voeg een TextBox, een Button en een Calendar Control toe.

Geef passende ID's aan de Controls, zet de eigenschap Visible van de Calendar op false.

Maak de kalender op via Auto Format...

75

Frank Horemans

Page 76: Cursus ASP.net 1

Default.aspx<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Src="Kalender.ascx" TagName="Kalender" TagPrefix="uc1" %>

<!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> <table> <tr> <td valign="top"> Geboortedatum:</td> <td> <uc1:Kalender ID="Kalender1" runat="server" /> </td> </tr> <tr> <td valign="top"> Datum in dienst:</td> <td> <uc1:Kalender ID="Kalender2" runat="server" /> </td> </tr> </table> </div> </form></body></html>

Geef volgende code in voor de CodeBehind file Kalender.ascx.cs: using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;

76

Frank Horemans

Page 77: Cursus ASP.net 1

public partial class Kalender : System.Web.UI.UserControl{ protected void Page_Load(object sender, System.EventArgs e)

{TxtDatum.Style["Text-align"] = "right";

}

protected void BtnSelecteer_Click(object sender, System.EventArgs e)

{Kal.Visible = !Kal.Visible;

}

protected void Kal_SelectionChanged(object sender, System.EventArgs e)

{TxtDatum.Text =

Kal.SelectedDate.ToShortDateString();Kal.Visible = false;

}

}

In designweergave van Default.aspx zie je nu de User Control

Voer de toepassing uit

Eigenschappen definiëren - Inloggen.ascx

User Controls kunnen ook eigenschappen hebben, deze kan je net zo eenvoudig instellen als bij de Web Form controls.

We maken een toepassing waarvoor we een User Control maken waarin de gebruiker een gebruikersnaam en een paswoord kan ingeven.

Voeg een Web User Control toe, geef deze de naam Inloggen

77

Frank Horemans

Page 78: Cursus ASP.net 1

Inloggen.ascx<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Inloggen.ascx.cs" Inherits="Inloggen" %>

<style type="text/css"> .UCLogin { BORDER: 1px solid <%= RandKleur %> }</style>

<table class="UCLogin"> <tr> <td> <asp:Label ID="Label1" runat="server" Text="Gebruikersnaam"></asp:Label></td> <td style="width: 158px"> <asp:TextBox ID="TxtGnaam" runat="server"></asp:TextBox></td> </tr> <tr> <td> <asp:Label ID="Label2" runat="server" Text="Paswoord"></asp:Label></td> <td style="width: 158px"> <asp:TextBox ID="TxtPwd" runat="server" TextMode="Password"></asp:TextBox></td> </tr> <tr> <td> </td> <td style="width: 158px"> <asp:Button ID="BtnInloggen" runat="server" Text="Inloggen" OnClick="BtnInloggen_Click" /></td> </tr></table>

Je merkt dat we met CSS een opmaak voorzien voor de tabel die de controls omvat. De waarde van de eigenschap RandKleur wordt runtime in de CSS-klasse UCLogin ingegeven.

In de CodeBehind-file Inloggen.ascx.cs voorzie je volgende code:

using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;

78

Frank Horemans

Page 79: Cursus ASP.net 1

using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;

public partial class Inloggen : System.Web.UI.UserControl{ private string randkleur;

public string RandKleur { get { return randkleur; } set { randkleur = value; } }

protected void Page_Load(object sender, EventArgs e) { if (TxtGnaam.Text == "") { TxtGnaam.Text = "Naam a.u.b."; TxtGnaam.Attributes["onclick"] = "this.value=''"; } else { TxtGnaam.Attributes["onclick"] = "void(0)"; } }}

Maak een Web Form aan waarin je de User Control gebruikt:

InlogScherm.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="InlogScherm.aspx.cs" Inherits="InlogScherm" %>

<%@ Register Src="Inloggen.ascx" TagName="Inloggen" TagPrefix="uc1" %>

<!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> <uc1:Inloggen ID="Inloggen1" runat="server" RandKleur="red" /> </div> </form></body></html>

Je merkt dat we de eigenschappen van de User Control met attributen kunnen aangeven, precies zoals in gewone Web Form Controls.

79

Frank Horemans

Page 80: Cursus ASP.net 1

8.2 Custom Controls

Custom Controls

In de voorgaande voorbeelden hebben we een User Control gemaakt door bestaande Controls te gebruiken en samen te brengen tot een grotere control. Dergelijke controls worden opgeslagen in een ascx-bestand binnen je Web Site.

Je kan Custom Controls maken door over te erven van een bestaande control. Dergelijke controls huizen in een Control Library en worden gecompileerd in een assembly.

TextBoxSpeciaal

We maken een control die overerft van een gewone TextBox en zorgen ervoor dat wanneer de eigenschap Enabled op false staat, de TextBox als gewone tekst wordt getoond (zonder kadertje).

Hou de huidige Web Site geopend in Visual Studio Kies File > New Project > Visual c# > Windows > Windows Control Library Name: MijnControls Solution: Add to Solution Kies een geschikte locatie Add > new item... > Web Custom Control: TextBoxSpeciaal.cs Verwijder WebCustomControl1.cs

TextBoxSpeciaal.cs

using System;using System.Collections.Generic;using System.ComponentModel;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;

namespace MijnControls{ [DefaultProperty("Text")] [ToolboxData("<{0}:TextBoxSpeciaal runat=server>")] public class TextBoxSpeciaal : TextBox { [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)]

public string LabelCSS {

80

Frank Horemans

Page 81: Cursus ASP.net 1

get { return ((string)ViewState["LabelCSS"]); } set { ViewState["LabelCSS"] = value; } }

protected override void Render(HtmlTextWriter output) { if (!this.Enabled) { //toon enkel de tekst output.Write(@"{1}", this.LabelCSS, this.Text);

} else { //render volgens de normale manier base.Render(output); } } }}

Onze Control erft over van de TextBox-control, standaard wordt overgeërfd van WebControl.

Merk ook op dat een aantal attributen gespecifiëerd staan boven de klassedeclaratie:

DefaultProperty: eigenschap die gevuld wordt wanneer iemand een waarde toekent aan de component in plaats van aan een eigenschap van de component

ToolBoxData: tag die wordt gegenereerd wanneer we de component op een Web Form slepen.

We overriden in deze klasse de methode Render uit de basisklasse. In de methode Render geef je aan welke HTML-output door de control moet worden gegenereerd.

Standaard wordt in een Web Custom Control de methode RenderContents overridden uit de klasse WebControl, dit hebben we hier niet nodig.

We hebben een eigenschap LabelCSS voorzien waarmee we de CSS-klasse kunnen instellen wanneer de control niet enabled is. De waarde van deze eigenschap wordt onthouden in de ViewState.

Zorg ervoor dat een dll-gecompileerd wordt voor de klasse TxtSpeciaal: Build > Build MijnControls

Maak in de Web Site een nieuwe Web Form: GebruikTextBoxSpeciaal.aspx Leg in de Web Site een referentie naar MijnControls.dll uit de Bin>Debug map

van de ControlLibrary MijnControls Sleep uit de Toolbox een TextBoxSpeciaal TxtTest op de Web Form Zorg ook voor een Button: BtnToggleEnabled

GebruikTextBoxSpeciaal.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GebruikTextBoxSpeciaal.aspx.cs" Inherits="GebruikTextBoxSpeciaal" %>

<%@ Register Assembly="MijnControls" Namespace="MijnControls" TagPrefix="cc1" %>

81

Frank Horemans

Page 82: Cursus ASP.net 1

<!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> <style type="text/css"> .rood {background-color:red;color:yellow} </style></head><body> <form id="form1" runat="server"> <div> <cc1:textboxspeciaal id="TxtTest" runat="server" LabelCSS="rood"></cc1:textboxspeciaal> <br /> <asp:Button ID="BtnToggleEnabled" runat="server" Text="Disable" OnClick="BtnToggleEnabled_Click" /></div> </form></body></html>

GebruikTextBoxSpeciaal.aspx.cs

...protected void BtnToggleEnabled_Click(object sender, EventArgs e){ TxtTest.Enabled = !TxtTest.Enabled; if (TxtTest.Enabled) BtnToggleEnabled.Text = "Disable"; else BtnToggleEnabled.Text = "Enable";}...

CustomBox

We maken nog een Custom Control: een uitklapbare box met titel en inhoud. De pagina houdt met cookies bij wat de status van elke box is.

82

Frank Horemans

Page 83: Cursus ASP.net 1

Voeg een Web Custom Control toe aan de library MijnControls: CustomBox.cs Plaats een figuur met dezelfde naam als de klasse in de rootfolder van de Control

Library: CustomBox.bmp Vraag de eigenschappen van de figuur op en stel in: Build Action: embedded

resource Download de nodige figuren en plaats ze in een submap images van het project We maken vijf private variabelen en hun eigenschappen aan:

inhoud: inhoud van de box - string titel: titel van de box - string breedte: breedte van de box - Unit open: moet de box standaard zichtbaar zijn ? - bool volgnr: eigen volgnr van de control

We declareren een statische variabele aantal, zodat we weten hoeveel CustomBoxen geplaatst werden, dit aantal schrijven we voor elke box weg in de instantievariabele volgnr, zodoende heeft elke box zijn eigen volgnr

We maken vier methoden die een StringBuilder retourneren. Door een StringBuilder te gebruiken worden grotere strings intern sneller verwerkt. We overriden de methode Render om de HTML-output van de control op te geven.

o MaakCode: stijldefinities en javascript-functies voor onze CustomBoxen CSS stijlblok tussen style-tags Javascript codeblok stussen script-tags

Functie BoxInhoud: Wordt uitgevoerd bij het klikken op openen/sluiten van de box. Zorgt voor zichtbaar/onzichtbaar maken van de inhoud Schrijft een cookie weg met de toestand

functie setCookie: Javascript-routine om een cookie weg te schrijven We moeten dit client-side doen daar het drukken op openen/sluiten geen postback veroorzaakt, maar client-side wordt afgehandeld

Deze code wordt slechts 1 keer op de pagina geplaatst, voor de box met volgnr 1.

o MaakKop: maakt een titeldeel voor een box aan. o MaakInhoud: maakt een raamwerk voor de inhoud van de box aan, hierin

wordt later de eigenschap Inhoud in gedumpto MaakVoet: zorgt voor een correct afsluiting van de HTML-tags o Render: override de Render methode van een control

Leest de statuswaarde voor de box uit een cookie en vult de eigenschap Open met de waarde true of false

zorgt ervoor dat de Kop, de Inhoud en de Voet op de pagina worden geplaatst

CustomBox.cs

83

Frank Horemans

Page 84: Cursus ASP.net 1

using System;using System.Collections.Generic;using System.ComponentModel;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Drawing;

namespace MijnControls{ [DefaultProperty("Text")] [ToolboxData("<{0}:CustomBox runat=server></{0}:CustomBox>")]

public class CustomBox : WebControl { [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)]

#region "vars en properties"

private string inhoud; private string titel; private static Unit breedte; private bool open;

// eigen volgnr van de control private int volgnr;

// aantal aangemaakte CustomBoxen private static int aantal = 0;

public CustomBox() { aantal++; volgnr = aantal; } /// De tekst die in de box moet verschijnen, /// kan zichtbaar en onzichtbaar worden gemaakt public string Inhoud { get { return inhoud; } set { inhoud = value; } }

/// De titel voor een box, /// wordt steeds getoond public string Titel { get { return titel; } set { titel = value; } }

/// Aangeven met een boolean of de inhoud moet worden weergegeven /// bij openen van de pagina public bool Open {

84

Frank Horemans

Page 85: Cursus ASP.net 1

get { return open; } set { open = value; } }

/// Breedte van de CustomBox public override Unit Width { get { return breedte; } set { breedte = value; } }

/// Breedte van de CustomBox private int Aantal { get { return aantal; } set { aantal = value; } }

#endregion

#region "methoden"

private StringBuilder MaakCode() { StringBuilder sb = new StringBuilder(); sb.Append("");

if (volgnr == 1) { //stijlblok toevoegen sb.Append("<style> " + "BODY { margin: 10px 10px 10px 10px; }" + ".CustomBox { width: " + Width + "; border-width: 0px; }" + ".CustomBox .Hoofd { height: 25px; background-color: #CCCCCC; " + "color: #6699CC; font-weight: bold; font-size: x-small; " + "font-family: verdana, arial, helvetica; }" + ".CustomBox .Hoofd TD { border-top: solid 1px #6699CC; " + "border-bottom: solid 1px #6699CC; }" + ".CustomBox .Hoofd .Hoekcel { border-top: solid 0px #6699CC; }" + ".CustomBox .Inhoud { color: Black; font-size: x-small; " + "font-family: verdana, arial, helvetica; }" + ".CustomBox .Inhoud TD { border-bottom: solid 1px #6699CC; " + "border-left: solid 1px #6699CC; border-right: solid 1px #6699CC; }" + ".HandCursor { cursor: hand; }" + ".Text { }" + "</style>");

// Javascript functies toevoegen sb.Append("<script language=javascript>" + "function Boxinhoud( obj, cbid )" + "{"

85

Frank Horemans

Page 86: Cursus ASP.net 1

+ "var inhoudBox = document.getElementById('Inhoud' +cbid );" + "var datum = new Date();" + "datum.setDate(datum.getDate()+5);"

+ "if ( inhoudBox.style.display == 'none' )" + "{ " + "inhoudBox.style.display = 'block';" + "obj.src = 'images/CustomBox_sluit.gif';" + "setCookie(cbid,'true',datum);" + "}else{" + "inhoudBox.style.display = 'none';" + "obj.src = 'images/CustomBox_open.gif';" + "setCookie(cbid,'false',datum);" + "}" + "}"

+ "function setCookie(name, value, expires)" + "{" + "document.cookie= name + '=' + escape(value) +" + "((expires) ? '; expires=' + expires.toGMTString() : '')" + "}" + "</script>"); } return sb; }

private StringBuilder MaakKop(string breedte, string titel) { StringBuilder sb = new StringBuilder(); sb.Append("<table id='" + this.ID + "'class='CustomBox' cellpadding='0' cellspacing='0'>" + "<tr class='Hoofd'>" + "<td width='1%' align='left' class='Hoekcel'>" + "<img src='images/CustomBox_linkerhoek.gif'>" + "</td>" + "<td width='97%'>" + "<span>" + Titel + " </span>" + "</td>" + "<td width='1%'>" + "<img src='images/CustomBox_" + (Open ? "sluit.gif" : "open.gif") + "' class='HandCursor' onclick='Boxinhoud( this, \"" + this.ID + "\" )'>" + "</td>" + "<td width='1%' align='right' class='Hoekcel'>" + "<img src='images/CustomBox_rechterhoek.gif'>" + "</td>" + "</tr>" + "</table>"); return sb; }

private StringBuilder MaakInhoud()

86

Frank Horemans

Page 87: Cursus ASP.net 1

{ StringBuilder sb = new StringBuilder(); sb.Append("<table id='Inhoud" +this.ID +"' class='CustomBox' " +"cellpadding='0' cellspacing='0' style='display: " + (Open ? "block" : "none") + "';>" + "<tr class='Inhoud'>" + "<td><!-- Inhoud Begin -->"); return sb; }

private StringBuilder MaakVoet() { StringBuilder sb = new StringBuilder(); sb.Append("<!-- Inhoud Einde --></td></tr></table>"); return sb; }

protected override void Render(HtmlTextWriter output) { for (int i = 0; i < Page.Request.Cookies.Count; i++) { HttpCookie cookie = Page.Request.Cookies[i];

if (cookie.Name.Equals(this.ID) == true) { Open = Convert.ToBoolean(cookie.Value); } }

output.Write( MaakCode().ToString() + MaakKop(Width.ToString(), Titel).ToString() + MaakInhoud().ToString() + Inhoud + MaakVoet().ToString()); }

public override void Dispose() { Aantal = 0; base.Dispose(); } #endregion }}

Maak in je Web Site een nieuwe Web Form: GebruikCustomBox Leg een referentie naar CustomBox.dll. Kopiëer de submap images in de Web Site Sleep een CustomBox op en Web Form. Maak een toepassing waarin je CustomBoxen gebruikt, stel de eigenschappen

Titel, Inhoud, Open en Width in.

Opmerking: zoals je merkt moet je ervoor zorgen dat de figuren beschikbaar zijn in je Web Site. Het is daardoor meestal handig ervoor te zorgen dat Custom Controls "self-contained" zijn en geen externe bestanden nodig hebben. Maar ja, het is eens leuk iets met figuurtjes te doen :)

87

Frank Horemans

Page 88: Cursus ASP.net 1

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GebruikCustomBox.aspx.cs" Inherits="GebruikCustomBox" %>

<%@ Register Assembly="MijnControls" Namespace="MijnControls" TagPrefix="cc1" %>

<!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> <h2>Inhoud</h2>

<table cellspacing="10" border="0"><tr>

<td valign="top"><cc1:CustomBox id="CustomBox1" runat="server" Width="150px" Inhoud="Leve ASP.net<br>Volg ASP.net aan het <a href='http://www.ivobrugge.be/cursusweb'>IVO Brugge</a>"

titel="ASP.net" Open="True"></cc1:CustomBox></td>

<td valign="top"><cc1:CustomBox id="CustomBox2" runat="server" Width="150px" Inhoud="Leuk hoor, werken met Custom Controls"

titel="Control"></cc1:CustomBox>  

<p></p></td>

</tr><tr>

<td valign="top"><cc1:CustomBox id="Custombox3" runat="server" Width="150px" Inhoud="Leve Java<br>Volg Java aan het <a href='http://www.ivobrugge.be/cursusweb'>IVO Brugge</a>"

titel="Java" Open="True"></cc1:CustomBox></td>

<td valign="top"><cc1:CustomBox id="Custombox4" runat="server" Width="150px" Inhoud="Dit is een server-side Custom Box"

titel="<span style='color:red'>Belangrijk</span>" Open="true"></cc1:CustomBox>

<p></p></td>

</tr></table>

</div> <br /> <asp:Button ID="Button1" runat="server" Text="PostBack" /> </form></body></html>

88

Frank Horemans

Page 89: Cursus ASP.net 1

8.3 Composite Controls

Wat zijn Composite Controls

Composite Controls of samengestelde controls stellen je in staat meerdere controls te bundelen in één gecompileerde Custom control.

Hiertoe maak je een klasse voor je Control met volgende kenmerken:

Override de methode CreateChildControls van de klasse Control om instanties te maken van de deelcontrols en ze toe te voegen aan de collectie Controls.

Implementeer de interface System.Web.UI.INamingContainer die ervoor zorgt dat de deelcontrols intern unieke namen krijgen toegewezen.

Een Composite Control maken

Met VS.net kan je als volgt een Composite Control maken:

Nieuw project: new User Control Library: MaakCompositeControl sluit en verwijder de automatisch aangemaakte klasse WebCustomControl add new item > UI > Web Custom Control > TekstControl

using System;using System.Web.UI;using System.Web.UI.WebControls;using System.ComponentModel;using System.Drawing; // voor de bitmap

namespace MaakCompositeControl{ /// <summary> /// Summary description for TekstControl. /// </summary> [DefaultProperty("Text"), ToolboxData("<{0}:TekstControl runat=server></{0}:TekstControl>"), ToolboxBitmap(@"D:\William\WWW\Cursusweb\ASPNET\h7\MaakCompositeControl\TekstControl.bmp") ] public class TekstControl : System.Web.UI.WebControls.WebControl, INamingContainer {

[Bindable(true), Category("Appearance"), DefaultValue("")]

protected override void CreateChildControls() { LiteralControl lc = new LiteralControl("<h1>ASP.net Composite Control</h1>"); Controls.Add(lc);

TextBox txt = new TextBox(); Controls.Add(txt); }

89

Frank Horemans

Page 90: Cursus ASP.net 1

}}

Je kan met VS.net ook een bitmap aanmaken voor later gebruik in de toolbox:

add new item > Resources > Bitmap file Via de eigenschappen stel de hoogte en breedte in op 16px Maak een tekeningtje zoals dit: Geef de naam TekstControl.bmp Pas het pad aan in de klasse TekstControl zodat je bmp-file gevonden wordt

Je kan nu een ASP.net Web Application maken, de component op de toolbox plaatsen en gebruiken in een WebForm: Het resultaat in HTML-weergave:

<%@ Register TagPrefix="cc1" Namespace="MaakCompositeControl" Assembly="MaakCompositeControl" %><%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="GebruikCompositeControl.WebForm1" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ><HTML>

<HEAD><title>WebForm1</title><meta name="GENERATOR" Content="Microsoft Visual Studio .NET

7.1"><meta name="CODE_LANGUAGE" Content="C#"><meta name="vs_defaultClientScript" content="JavaScript"><meta name="vs_targetSchema"

content="http://schemas.microsoft.com/intellisense/ie5"></HEAD><body>

<form id="Form1" method="post" runat="server"><cc1:TekstControl id="TekstControl1"

runat="server"></cc1:TekstControl></form>

</body></HTML>

We kunnen vanuit een Composite control ook eigenschappen gebruiken. Hiermee kunnen we bijvoorbeeld eigenschappen van de deelcontrols aan de buitenwereld kenbaar maken.

We moeten er bij het aanspreken van de eigenschappen van de individuele controls wel zeker zijn dat ze reeds geplaatst werden in de composite control. We kunnen er voor zorgen dat de methode CreateChildControls zeker uitgevoerd is met de methode EnsureChildControls.

using System;using System.Web.UI;using System.Web.UI.WebControls;using System.ComponentModel;using System.Drawing;

namespace MaakCompositeControl

90

Frank Horemans

Page 91: Cursus ASP.net 1

{ /// <summary> /// Summary description for TabelControl. /// </summary> [DefaultProperty("Text"), ToolboxData("<{0}:TekstControl runat=server></{0}:TekstControl>"), ToolboxBitmap(@"D:\William\WWW\Cursusweb\ASPNET\h7\MaakCompositeControl\TekstControl.bmp") ] public class TekstControl : System.Web.UI.WebControls.WebControl, INamingContainer { private string titel;

private TextBox txt;

public string Titel { get { return titel; } set { titel = value; } }

public string Tekst { get { EnsureChildControls(); return txt.Text; } set { EnsureChildControls(); txt.Text = value; } }

[Bindable(true), Category("Appearance"), DefaultValue("")]

protected override void CreateChildControls() { LiteralControl lc = new LiteralControl("<h1>" +Titel +"</h1>"); Controls.Add(lc);

txt = new TextBox(); Controls.Add(txt); }

}}

In een Web Application kunnen we nu de eigenschappen voor de Composite Control instellen:

91

Frank Horemans

Page 92: Cursus ASP.net 1

<cc1:TekstControl id="TekstControl1" titel="Hoera!" tekst="invulveld" runat="server"></cc1:TekstControl>

8.4 Oefeningen

Toepassing: dynText

Maak een User Control die overerft van een standaard TextBox. Wanneer de gebruiker de dynText-Control de focus heeft krijgt deze een achtergrondkleur. Wanneer de dynText de focus verliest (blur) dan krijgt deze de standaardkleur.

De 'focuskleur' is door de gebruiker met behulp van een eigenschap in te stellen.

92

Frank Horemans

Page 93: Cursus ASP.net 1

9 ASP.NET : DYNAMISCHE CONTROLS

1. Wat zijn Dynamische Controls ? 2. Dynamische Controls maken 3. Events bij Dynamische Controls 4. User Controls dynamisch laden 5. Oefeningen

9.1 Wat zijn Dynamische Controls ?

Dynamische controls zijn controls die je runtime aanmaakt. In plaats van gebruik te maken van de ToolBox en controls op een Web Form neer te plaatsen - of in de HTMLcode de tag voor een control in te geven - maak je de control runtime aan.

Als je controls runtime aanmaakt voeg ze toe aan de Controls-collectie van de pagina of van een andere Control.

Daar we graag controle hebben op de plaatsing van de runtime controls plaatsen we een PlaceHolder Control op plaats waar we dynamische gemaakte controls willen plaatsen. Deze Control houdt gewoon plaats voor andere controls.

9.2 Dynamische Controls maken: OnInit

We plaatsen een PlaceHolder en een Button op de pagina, zodat we kunnen experimenteren met PostBack.

We maken nu runtime een TextBox aan en voegen die toe via de PlaceHolder.

Wanneer je drukt op de knop verdwijnt de TextBox!

<pre>using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;

namespace LaadControls{

/// <summary>/// Summary description for Inleiding./// </summary>public class Inleiding : System.Web.UI.Page{

protected System.Web.UI.WebControls.PlaceHolder PH; protected System.Web.UI.WebControls.Button btnVerzenden;

private void Page_Load(object sender, System.EventArgs e)

93

Frank Horemans

Page 94: Cursus ASP.net 1

{ if(!IsPostBack) { TextBox txt = new TextBox(); PH.Controls.Add(txt); txt.Text = "Starttekst"; }

}

...}

Gezien elke webaanvraag onafhankelijk wordt gezien door de server wordt bij een PostBack de TextBox niet meer aangemaakt. Run-time Controls moet je bijgevolg bij elke pagina-aanvraag opnieuw aanmaken.

We doen een aanpassing in de code en voegen nog een Label toe met de ToolBox:

public class Inleiding : System.Web.UI.Page{

protected System.Web.UI.WebControls.PlaceHolder PH; protected System.Web.UI.WebControls.Label lblTest; protected System.Web.UI.WebControls.Button btnVerzenden;

private void Page_Load(object sender, System.EventArgs e){

TextBox txt = new TextBox(); PH.Controls.Add(txt); txt.Text = "Starttekst"; lblTest.Text = txt.Text;

}}

Verander de tekst in de TextBox en druk op de knop. Je merkt dat de tekst in de TextBox aangepast blijft, door de ViewState. De ViewState wordt echter weggeschreven na de Page_Load: de tekst in de TextBox wordt dus eerst Starttekst door de Page_Load en wordt achteraf door de ViewState aangepast tot de ingebrachte tekst. Aagezien de Page_Load routine nu reeds is uitgevoerd blijft de tekst van het Label Starttekst.

Meer hierover bij 4GuysFromRolla.

We doen volgende aanpassing:

private void Page_Load(object sender, System.EventArgs e){

lblTest.Text = ((TextBox)FindControl("T1")).Text;}

override protected void OnInit(EventArgs e){

...

94

Frank Horemans

Page 95: Cursus ASP.net 1

TextBox txt = new TextBox(); PH.Controls.Add(txt); txt.Text = "Starttekst"; txt.ID = "T1"; ...

}

We zetten het maken van de control in de routine Page_OnInit: deze routine wordt uitgevoerd voor de ViewState wordt geladen. We schrijven dus initieel de tekst StartTekst in de TextBox. Na OnInit wordt de ViewState geladen. De tekst in de TextBox verandert hierdoor in de waarde die de gebruiker heeft ingegeven. Een verwijzing naar de TextBox in Page_Load zorgt er nu voor dat de reële waarde uit de ViewState wordt ingelezen. Hierdoor kunnen we ervoor zorgen dat de juiste waarde zowel in de TextBox als in het Label verschijnen.

Hier gebruiken we de methode FindControl om een referentie op te bouwen naar de TextBox. Je kan natuurlijk ook werken met een instantievariabele:

protected TextBox txt;

private void Page_Load(object sender, System.EventArgs e){

lblTest.Text = txt.Text;}

9.3 Event Handlers bij dynamische controls

Een probleem met dynamische controls is dat wanneer je een editor als Visual Studio gebruikt, je misschien gewoon bent om event hanler-methoden te installeren door eenvoudigweg de eigenschappen van een control op te vragen in design-modus.

Met dynamisch gecreëerde controls kan dit natuurlijk niet. Je zal de event-hanlers dus zelf moeten koppelen.

In deze toepassing laten we 5 CheckBox-controls verschijnen en zorgen we voor een gepaste melding wanneer deze controls gemanipuleerd worden.

We voorzien een variable boxen op klasseniveau, deze variabele bevat een array van CheckBox-controls.

In de methode OnInit doen we een aanroep van de metode LaadUI, hierin bouwen onze dynamische controls op. We voorzien elke CheckBox van een event-handler voor het event CheckedChanged.

95

Frank Horemans

Page 96: Cursus ASP.net 1

using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;

namespace LaadControls{

/// <summary>/// Summary description for DynamicEvent./// </summary>public class DynamicEvent : System.Web.UI.Page{

protected System.Web.UI.WebControls.PlaceHolder PH; protected System.Web.UI.WebControls.Label lblVerander; protected CheckBox[] boxen;

private void Page_Load(object sender, System.EventArgs e){

// Put user code to initialize the page here}

private void LaadUI() { int aantal = 5; boxen = new CheckBox[aantal]; for(int i = 0; i < aantal; i++) { boxen[i] = new CheckBox(); boxen[i].ID = "Box" +i.ToString();

96

Frank Horemans

Page 97: Cursus ASP.net 1

boxen[i].AutoPostBack = true; boxen[i].Text = "Kruis me aan"; boxen[i].CheckedChanged += new EventHandler(this.CB_CheckedChanged); PH.Controls.Add(boxen[i]); } }

private void CB_CheckedChanged(object sender, System.EventArgs e) { CheckBox cb = (CheckBox)sender; lblVerander.Text += "Verandering in: " +cb.ID +"<br>" +"Waarde is nu: " +cb.Checked +"<p>"; }

#region Web Form Designer generated codeoverride protected void OnInit(EventArgs e){

//// CODEGEN: This call is required by the ASP.NET Web

Form Designer.//InitializeComponent();base.OnInit(e);

LaadUI();}

/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){

this.Load += new System.EventHandler(this.Page_Load);

}#endregion

}}

9.4 User Controls dynamisch laden

In het vorige hoofdstuk leerden we User Controls aanmaken. Deze controls kunnen we ook dynamisch laden.

Werk je met een User Control in een ascx-bestand, dan gebruik je de methode LoadControl. Voeg de kalendercontrol toe in het huidige project via de Solution Explorer: add Existing Item. Selecteer het ascx-bestand, VS.net zal automatisch het ascx.cs bestand meekopiëren. Vanzelfsprekend kan je het pad naar de ascx-file ook relatief opbouwen naar de originele locatie.

Werk je met een gecompileerde User Control in een dll-bestand, dan hoef je enkel een referentie te leggen naar de dll en kan je de control gebruiken als een gewone control.

97

Frank Horemans

Page 98: Cursus ASP.net 1

Vergeet de using clausule bovenaan de pagina niet als je de naam van de namespace niet telkens wenst in te tikken.

Hier maken we ook kennis met een nieuwe Web Control: Literal. Met deze control kan je een letterlijk stukje tekst invoegen. Hier gebruiken we een Literal om een P-tag tussen onze controls in te voegen.

using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using MaakCustomBox;

namespace LaadControls{

/// <summary>/// Summary description for dynUserControl./// </summary>public class dynUserControl : System.Web.UI.Page{

protected System.Web.UI.WebControls.PlaceHolder ph;

private void Page_Load(object sender, System.EventArgs e){

// Put user code to initialize the page here}

private void LaadUI() { Control kal = LoadControl("Kalender.ascx"); ph.Controls.Add(kal); Literal l = new Literal(); ph.Controls.Add(l); l.Text = "<p>";

CustomBox cb = new CustomBox(); ph.Controls.Add(cb); cb.ID = "CB"; cb.Inhoud = "Een dynamische Custom Box"; cb.Titel = "CB"; cb.Width = new Unit("200px");

98

Frank Horemans

Page 99: Cursus ASP.net 1

}

#region Web Form Designer generated codeoverride protected void OnInit(EventArgs e){

//// CODEGEN: This call is required by the ASP.NET Web

Form Designer.//InitializeComponent();base.OnInit(e);

LaadUI();}

/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){

this.Load += new System.EventHandler(this.Page_Load);

}#endregion

}}

9.5 Oefeningen

Toepassing: dynText

Maak een User Control die overerft van een standaard TextBox. Wanneer de gebruiker de dynText-Control de focus heeft krijgt deze een achtergrondkleur. Wanneer de dynText de focus verliest (blur) dan krijgt deze de standaardkleur.

De 'focuskleur' is door de gebruiker met behulp van een eigenschap in te stellen.

99

Frank Horemans

Page 100: Cursus ASP.net 1

10 ASP.NET : DATA BINDING EN LIST CONTROLS

10.1 Inleiding

De meeste dynamische websites en zowat alle web-gebaseerde applicaties vereisen wellicht toegang tot een gegevensbron (data source). In de cursus C sharp maakten we al kennis met ArrayList en HashTableIn de cursus ADO.Net leerden we DataSet, DataTable, DataView, SqlDataReader kennen. Deze kennis zullen we hier opnieuw nodig hebben. We zullen hier ook kennis maken met een aantal nieuwe ASP.Net server controls zoals de Repeater, GridView en DataList controls.

Start een nieuwe Blank Solution in VS 2005: ListControls Voeg een Web Site toe: Site Verwijder Default.aspx

10.2 Data Binding Syntax

Het principe van server-side databinding is om ASP.NET zo ver te krijgen dat het een of meer waarden van een datasource in een control op een webpagina opneemt. De basissyntax hiervoor lijkt op een server-side scriptblok, met een '#' - karakter als indicator dat het hier om een databinding opdracht gaat.

<%# naam van databron %>

Een dergelijk codeblok bevat geen uitvoerbare opdrachten maar specifieke databinding opdrachten. Er zijn twee scenario's waarin we een control wensen te binden aan een databron :

Single-value data binding: we hebben een enkelvoudige waarde die we aan een control wensen te binden. Bv. we wensen een attribuut van een control op een waarde in te stellen uit een gegevensbron.

Repeated-value data binding: de databron bevat meerdere waarden. We willen bijvoorbeeld een ListBox vullen met een aantal waarden.

10.3 Single Value data binding

Voeg een nieuwe Web Form toe: SingleValue.aspx

100

Frank Horemans

Page 101: Cursus ASP.net 1

in SingleValue.aspx.cs

protected string titel = "Data binding";

protected string Figuur{ get { return "eekhoorn.jpg"; }}

public int TelOp (int a, int b){ return a + b;}

private void Page_Load(object sender, System.EventArgs e){

if(!IsPostBack) DataBind();}

in SingleValue.aspx

<form id="Form1" method="post" runat="server"><h1><%# titel %></h1><asp:Image id="Image1" runat="server" ImageUrl='<%# "images/"

+Figuur %>'></asp:Image><br/><asp:Label id="Label1" runat="server"><%# "bron van de figuur:

" +Image1.ImageUrl %></asp:Label><h2><%# "Optellen van 4 en 8 levert: " +TelOp(4,8) %></h2>

</form>

Hier gebruiken we single-value databinding op een aantal verschillende manieren.

databinding aan een variabele databinding aan een eigenschap

101

Frank Horemans

Page 102: Cursus ASP.net 1

databinding aan een eigenschap van een control databinding aan de retourwaarde van een methode

Om de binding te activeren staat in de Page_Load methode de opdracht DataBind. Met deze methode van de Page-klasse zorg je ervoor dat alle controls gebonden worden. Het is de enige methode om er voor te zorgen dat we databinding verkrijgen zoals hierboven: databinding waarbij de binding niet in een control gebeurt. Gebruik je Controls die databinding ondersteunen, dan kan je de DataBind methode van de control gebruiken.

10.4 Repeated-Value data-binding: basisprincipes

Data-binding wordt pas heel interessant wanneer je gebruik maakt van een bron die meerdere waarden bevat. Elementen die als DataSource kunnen dienen zijn:

Collecties: ArrayList, HashTable, Request.Form, ... ADO.net collecties: DataSet, DataView, DataReader, ... Eigen collecties van objecten

In ASP.net zijn er Controls die kunnen gebonden worden aan een datasource die meerdere items bevat:

DropDownList ListBox RadioButtonList CheckBoxList Repeater DataList GridView

De HTML-output die deze controls genereren hangt sterk af van eigenschappen die je instelt in de controls.

102

Frank Horemans

Page 103: Cursus ASP.net 1

DropDownList, ListBox, RadioButtonList en CheckBoxList kan je zonder enige moeite aan een Datasource koppelen met de methode DataBind.

Repeater, DataList en DataGrid koppel je aan een DataSource door gebruik te maken van templates: je kan voor elke waarde in de datasource opgeven welke inhoud op de pagina moet verschijnen en welke opmaak er moet worden toegepast.

10.5 Eenvoudige repeated-value data-binding: DropDownList, ListBox

In deze toepassing leren we hoe we op de eenvoudigste manier aan repeated-value data-binding doen. We zullen hiervoor meteen gebruik maken van een gelaagde architectuur:

o Prestentation: GUI met Server Controls o Logic: logica en eigen klassen met custom objecten o DAL: ophalen van de gegevens

De Presentatielaag raadpleegt de Logic-laag, de Logic-laag raadpleegt de DAL-laag. We zorgen ervoor dat telkens enkel met de buurlaag verbonden wordt: Presentatie mag dus niet rechtsreeks met DAL verbinden.

Voeg aan de solution een nieuw project toe: Class Library: DAL Verwijder Class1.cs Voeg een nieuwe klasse DataAccess toe

DataAccess.cs

using System;using System.Collections;using System.Collections.Generic;using System.Text;

namespace DAL{ public class DataAccess { public static ArrayList GetGroenten() { ArrayList groenten = new ArrayList(); groenten.Add("Sla"); groenten.Add("Wortel"); groenten.Add("Prei"); groenten.Add("Selder"); groenten.Add("Paprika"); groenten.Add("Ui"); groenten.Add("Courgette");

groenten.Sort();

return groenten; }

public static Hashtable GetLanden() { Hashtable landen = new Hashtable();

103

Frank Horemans

Page 104: Cursus ASP.net 1

landen.Add("NL", "Nederland"); landen.Add("B", "Belgie"); landen.Add("Fr", "Frankrijk"); landen.Add("Lux", "Luxemburg");

return landen; } }}

Build de class library Voeg aan de solution een nieuw project toe: Class Library: Logic Leg een referentie naar DAL.dll Verwijder Class1.cs Voeg een nieuwe klasse Business toe:

using System;using System.Collections;using System.Collections.Generic;using System.Text;using DAL;

namespace Logic{ public class Business { public static ArrayList GetGroenten() { return DataAccess.GetGroenten(); }

public static Hashtable GetLanden() { return DataAccess.GetLanden(); } }}

Voeg aan de Site een referentie toe naar Logic.dll Sleep op een nieuwe pagina RepeatedValue.aspx twee DropDownLists en twee

ListBoxen. In de Page_Load routine vullen we deze objecten Met de methode DataBind van de pagina binden we alle controls.

De controls hebben zelf ook een methode DataBind, mocht je ze niet allen willen binden

...using Logic;

public partial class RepeatedValue : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) {

104

Frank Horemans

Page 105: Cursus ASP.net 1

DropDownList1.DataSource = Business.GetGroenten(); ListBox1.DataSource = Business.GetGroenten();

DropDownList2.DataSource = Business.GetLanden(); DropDownList2.DataTextField = "value"; DropDownList2.DataValueField = "key"; ListBox2.DataSource = Business.GetLanden(); ListBox2.DataTextField = "value"; ListBox2.DataValueField = "key";

DataBind(); } }}

We koppelen de ArrayList met groenten aan een DropDownList en een ListBox Voor de Hashtable ligt het iets gecompliceerder: deze heeft een key- en een value-

waarde. Geef deze waarde op voor de eigenschappen DataValueField (key) en DataTextField (tekstwaarde)

Je kan dit ook regelen met Visual Studio 2005, zonder code te moeten schrijven:

Sleep een DropDownList op de pagina Kies Choose DataSource...

Bij Select a datasource kies je voor new DataSource

105

Frank Horemans

Page 106: Cursus ASP.net 1

Kies voor Object (wij gaan niet rechstreeks met een database verbinden, maar gebruiken onze DAL-laag

Geef als ID ODSGroenten

106

Frank Horemans

Page 107: Cursus ASP.net 1

Kies Logic.Business als business object

107

Frank Horemans

Page 108: Cursus ASP.net 1

87

Beëindig de Wizard zonder verdere aanpassingen

108

Frank Horemans

Page 109: Cursus ASP.net 1

Voor de ListBox met de groenten kies je nu heel eenvoudig ODSGroenten als DataSource

Voor de DropDownList met landen maak je een nieuwe Object Data Source ODSLanden aan en geef je value en key in als display en value-waarden.

Je kan analoog werken voor een CheckBoxList en een RadioButtonList.

Merk op dat bij het werken met een ArrayList als bron, in de gegenereerde HTML-code voor de elementen het attribuut value dezelfde waarde krijgt als de eigenlijke tekst in de OPTION-tag.

10.6 Repeater - Container.DataItem - Eval

De control Repeater geeft je een volledige vrijheid in de manier waarop de items uit de DataSource op het scherm worden gepresenteerd. Wanneer je een Repeater op een pagina sleept krijg je in Visual Studio de melding om in HTML-view de Templates aan te passen. De Repeater control ondersteund een aantal templates. Hiemee kan je opgeven hoe de datagegevens op het scherm worden weergegeven:

Template Omschrijving

109

Frank Horemans

Page 110: Cursus ASP.net 1

ItemTemplateInhoud hiervan wordt herhaald voor elk item uit de DataSource. Deze template is vereist voor elke Repeater.

HeaderTemplateWordt weergegeven boven de items uit de DataSource

FooterTemplateWordt weergegeven onder de items uit de DataSource

AlternatingItemTemplate Inhoud en opmaak voor afwisselende items

SeparatorTemplate Wordt weergegeven tussen de verschillende items

Voorzie twee Repeaters.

Repeater.aspx.cs...using Logic;

public partial class Repeater : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Repeater1.DataSource = Business.GetGroenten(); Repeater2.DataSource = Business.GetLanden(); DataBind(); } }}

Om iets op het scherm te laten weergeven moeten we in de code de nodige aanpassingen doen:

<asp:Repeater id="Repeater1" runat="server" DataSource="<%# groenten %>">

<ItemTemplate>

110

Frank Horemans

Page 111: Cursus ASP.net 1

<%# Container.DataItem %></ItemTemplate><SeparatorTemplate>

-</SeparatorTemplate>

</asp:Repeater>

In het ItemTemplate zien we de opdracht:

<%# Container.DataItem %>

De opdracht Container.DataItem verwijst naar een item uit de DataSource van de Container-Control: de Repeater.

Als SeparatorTemplate werd hier een streepje opgegeven: de verschillende items worden gescheiden door een streepje.

Koppel je de tweede Repeater aan de Hashtable landen dan moet je weer specifiëren welk veld uit de DataSource je wenst weer te geven. Een Hashtable is een DictionaryEntry, we moeten het DataItem dus eerst typecasten naar deze klasse wanneer we de eigenschappen Key en Value willen aanspreken.

<asp:Repeater id="Repeater1" runat="server" DataSource="<%# groenten %>">

<ItemTemplate><%# ((DictionaryEntry)Container.DataItem).Key %> = <%#

((DictionaryEntry)Container.DataItem).Value %></ItemTemplate><SeparatorTemplate>

-</SeparatorTemplate>

</asp:Repeater>

Een andere manier om velden uit een Datasource op te vragen is met de methode Eval van de klasse DataBinder. Deze methode is intern trager dan de standaard databinding maar biedt ook een manier om gegevens in een bepaald formaat te zetten, in een optioneel derde argument. Je hoeft ook niet meer aan de typecasting te denken.

DataBinder.Eval

In ASP.Net 1.1 moet je werken met volgende syntax:

<%# DataBinder.Eval(Container.DataItem, expression [, format]) %>

Eval

Vanaf ASP.Net 2.0 kan je dit afkorten tot:

111

Frank Horemans

Page 112: Cursus ASP.net 1

<%# Eval(expression [, format]) %>

Het formaat geef je aan tussen accolades. Het formaat zal steeds beginnen met het cijfer nul, wat een plaatsvervanger is voor het echte item. Daarna tik je een dubbele punt gevolgd door het gewenste formaat. Meer over opmaak van gegevens op MSDN. Voorbeeld: "{0:#,##0,00}" als formaat geeft aan dat je een scheidingsteken wil voor de duizendtallen, zeker een cijfer voor het decimaal scheidingsteken wenst te zien, en twee cijfers erna.

Repeater met Custom Klasse

o Voeg in de DAL-klasse DataAccess een methode toe:

... public static DataTable GetFietsRoutes() { DataTable fietsroutes = new DataTable(); DataColumn id = new DataColumn("id"); id.DataType = typeof(int); fietsroutes.Columns.Add(id);

DataColumn naam = new DataColumn("naam"); naam.DataType = typeof(string); fietsroutes.Columns.Add(naam);

DataColumn afstand = new DataColumn("afstand"); afstand.DataType = typeof(float); fietsroutes.Columns.Add(afstand);

fietsroutes.Rows.Add(0, "Kastelenroute", 56); fietsroutes.Rows.Add(1, "Wijnendaleroute", 59); fietsroutes.Rows.Add(2, "Oude Dijkenroute", 43); fietsroutes.Rows.Add(3, "Riante Polderroute", 44); fietsroutes.Rows.Add(4, "Permekeroute", 27);

int aantal = fietsroutes.Rows.Count;

return fietsroutes; }

}}

o Voeg in de Class Library Logic een Class-file Fietsroute.cs toe met volgende drie klassen:

112

Frank Horemans

Page 113: Cursus ASP.net 1

Fietsroute.csusing System;using System.Collections;using System.Collections.Generic;using System.Text;using System.Data;using DAL;

namespace Logic{ public class Fietsroute { private int id;

public int Id { get { return id; } set { id = value; } }

private string naam;

public string Naam { get { return naam; } set { naam = value; } } private double afstand;

public double Afstand { get { return afstand; } set { afstand = value; } }

public Fietsroute() { }

public Fietsroute(int id, string naam, double afstand ) { Id = id; Naam = naam; Afstand = afstand; } }

public class Fietsroutecollection : CollectionBase { public Fietsroutecollection() { }

public void Add(Fietsroute f) { InnerList.Add(f); }

//indexer: "Item"-property

113

Frank Horemans

Page 114: Cursus ASP.net 1

public Fietsroute this[int index] { get { return (Fietsroute)InnerList[index]; } set { InnerList[index] = value; } } }

public class Fietsroutes { public static Fietsroutecollection GetFietsRoutes() { DataTable dt = DataAccess.GetFietsRoutes();

Fietsroutecollection fietsroutes = new Fietsroutecollection(); foreach (DataRow rij in dt.Rows) { Fietsroute f = new Fietsroute(); f.Id = Convert.ToInt32(rij["id"]); f.Naam = rij["naam"].ToString(); f.Afstand = Convert.ToDouble(rij["afstand"]); fietsroutes.Add(f); } return fietsroutes; } }}

o Voeg op een WebForm een Repeater toe voor het ophalen van fietsroutegegevens.

o Kies als Data Source een Object Data Source op basis van de klasse Logic.Fietsroutes en de methode GetFietsRoutes.

o Voorzie een ItemTemplate voor de Repeater:

<asp:Repeater ID="Repeater3" runat="server" DataSourceID="ODSFietsroutes"> <ItemTemplate> <%# Eval("Naam") +" (" + Eval("Afstand","{0:#,##0.0}") +")" %><br /> </ItemTemplate></asp:Repeater><asp:ObjectDataSource ID="ODSFietsroutes" runat="server" SelectMethod="GetFietsRoutes" TypeName="Logic.Fietsroutes"></asp:ObjectDataSource>

Attributen voor Object Data Sources

Voor het handige gebruik van Object Data Sources kan je gebruik maken van attributen voor je dataaccess-methoden in de Logic-layer. Op deze manier kan je gebruik maken van de optie "Show only data components" bij het instellen van de Object Data Source. Je kan ook aangeven welke methoden je gaat gebruiken voor SELECT, UPDATE, INSERT en DELETE-opdrachten.

Business.cs

114

Frank Horemans

Page 115: Cursus ASP.net 1

...namespace Logic{ [DataObject] public class Business { [DataObjectMethod(DataObjectMethodType.Select)] public static ArrayList GetGroenten() { return DataAccess.GetGroenten(); }

[DataObjectMethod(DataObjectMethodType.Select)] public static Hashtable GetLanden() { return DataAccess.GetLanden(); } }

}

Fietsroute.cs... [DataObject] public class Fietsroutes { [DataObjectMethod(DataObjectMethodType.Select)] public static Fietsroutecollection GetFietsRoutes() { DataTable dt = DataAccess.GetFietsRoutes(); int aantal = dt.Rows.Count;

Fietsroutecollection fietsroutes = new Fietsroutecollection(); foreach (DataRow rij in dt.Rows) { Fietsroute f = new Fietsroute(); f.Id = Convert.ToInt32(rij["id"]); f.Naam = rij["naam"].ToString(); f.Afstand = Convert.ToDouble(rij["afstand"]); fietsroutes.Add(f); } return fietsroutes; } }

115

Frank Horemans

Page 116: Cursus ASP.net 1

11 DATALIST

1. DataList: basis 2. DataList: items selecteren en deselecteren 3. Object Data Source hergebruiken met MasterPages 4. DataList: items bewerken 5. DataList: items toevoegen 6. DataList: items verwijderen

11.1 DataList: basisbegrippen

De klassen gebruikt in dit hoofdstuk werden aangemaakt in het vorige hoofdstuk data binding en list controls.

Weergave van items in een DataList

Een DataList stelt je in staat gegevens op het scherm te brengen waarbij de standaardlayout een kolom is. Deze control biedt opties voor auto-opmaak: naast het aanmaken van de inhoud met behulp van templates kan je deze keer ook telkens een Style voor de Template opgeven.

Deze Control biedt ook ondersteuning voor het bewerken van elementen.

In Visual Studio kan je op een WYSIWYG-manier een DataList opmaken:

Sleep een DataList op een Web Form

116

Frank Horemans

Page 117: Cursus ASP.net 1

Kies via Auto Format... voor Sand & Sky

Kies via Choose DataSource voor een nieuwe Object Data Source voor de groenten uit Logic.Business - GetGroenten

Kies voor Edit Templates van de DataList

Nu kan je de Item Templates WYSIWYG aanmaken

Sleep een Image in het onderdeel ItemTemplate Stel de ImageUrl in zodat een figuur geladen wordt

voorbeeld: images/komkommer.gif:

117

Frank Horemans

Page 118: Cursus ASP.net 1

Sleep een Label naast de figuur. Kies Edit Databindings... voor het Label

Kies End Template Editing voor de DataList Stel eventueel nog via de eigenschappen van de DataList een leuke ItemStyle en

AlternatingItemStyle in.

11.2 DataList: Items Selecteren en deselecteren

Items selecteren

Behalve de extra mogelijkheid om een Style voor de verschillende templates aan te geven zijn en de WYSIWYG-mogelijkheden van Visual Studio biedt een DataList nog extra mogelijkheden t.o.v. de Repeater. Je kan een mogelijkheid inbouwen om items te selecteren. Hiertoe onderneem je volgende extra stappen:

Maak een SelectedItemTemplate: tekst en controls die moeten getoond worden op de pagina wanneer de gebruiker een item selecteerd.

Voeg een Button, LinkButton of ImageButton toe en stel de eigenschap CommandName in op select

118

Frank Horemans

Page 119: Cursus ASP.net 1

Maak een event-handler voor het event SelectedIndexChanged van de DataList en bind de DataList opnieuw aan de DataSource.

Je kan deze actie ook onderscheppen met een ander CommandName in het event ItemCommand

Voorbeeld: fietsroutes

Voeg een DataList toe aan een Web Form Kies Auto Format... en kies het format "Slate" Kies Choose Data Source en maak een nieuwe DataSource ODSFiets voor de

fietsroutes uit Logic.Fietsroutes Kies Edit Templates

Je komt nu terecht in de ItemTemplate voor de DataList: de gewone weergave van een element uit de lijst. Daar we gebruik maken van een Custom Object wordt voor elke eigenschap al een tekst en een Label voorzien!

Wij wensen de details van een fietsroute te zien wanneer de gebruiker de betreffende fietsroute selecteert.

Knip de volledige inhoud van de ItemTemplate Kies Display: SelectedItemTemplate Plak hier de inhoud uit de ItemTemplate Doe volgende aanpassingen:

119

Frank Horemans

Page 120: Cursus ASP.net 1

De SelectedItemTemplate wordt getoond wanneer een item geselecteerd wordt. Dit selecteren doen we in de ItemTemplate. Kies Display: ItemTemplate

Voorzie een LinkButton

Kies Edit Databindings... voor de LinkButton Doe volgende instellingen om de Naam van de fietsroute in de LinkButton te zien.

Vraag de eigenschappen van de LinkButton op en stel de eigenschap CommandName in op select: wanneer op deze LinkButton geklikt wordt zal de SelectedItemTemplate worden getoond voor dit element.

Wanneer je de site uitvoert zal je merken dat het nog niet naar behoren werkt: je moet twee keer klikken om de ItemTemplate te zien, en bepaalde gegevens zijn niet ingevuld.

Dit heeft zijn oorzaak in het laden van de pagina: de ViewState bevat alle gegevens van de DataList die oorspronkelijk werden getoond, dus enkel de namen van de fietsroutes, doch niet de detailgegevens van een fietsroute.

120

Frank Horemans

Page 121: Cursus ASP.net 1

We kunnen dit corrigeren door na het selecteren van een Item de DataList opnieuw te binden met de DataSource. De DataSource zelf is nog steeds gekend daar deze door ASP.Net tags in onze .aspx pagina aan de DataList is gebonden.

Vraag de events op voor de DataList, maak een event-handler voor SelectedIndexChanged:

protected void DataList2_SelectedIndexChanged(object sender, EventArgs e){ DataList2.DataBind();}

De toepassing werkt nu zoals het hoort

Selectie opheffen: deselecteren

Kies in de DataList voor Display: SelectedItemTemplate Vervang het Label met de naam van de fietsroute door een LinkButton Stel de juiste databindings in om de naam weer te geven Stel de CommandName van de LinkButton in op unselect (vrij te kiezen) Voorzie een eventhandler voor het event ItemCommand van de DataList:

protected void DataList2_ItemCommand(object source, DataListCommandEventArgs e){ if (e.CommandName == "unselect") DataList2.SelectedIndex = -1; DataList2.DataBind();}

Je kan op analoge wijze het selecteren van een Item ook voorzien met de event ItemCommand in plaats van SelectedIndexChanged.

121

Frank Horemans

Page 122: Cursus ASP.net 1

11.3 ODS hergebruiken met Masterpages

In de voorgaande voorbeelden hebben we een aantal keer gebruik gemaakt van een Object Data Source: een Data Source waarbij we de gegevens manipuleren met behulp van onze eigen klassen.

Een ObjectDataSource maakt deel uit van de namespace System.Web.UI.WebControls

Om een ObjectDataSource te hergebruiken op verschillende pagina's kan je handig gebruik maken van MasterPages, in plaats van op elke pagina de ObjectDataSource opnieuw aan te maken.

Voeg een nieuw Item toe aan de Web Site: MasterPage: Meester.master Vul de pagina met een titeltekst: ODS in Masterpage Voeg de benodigde ObjectDataSources toe, vb ODSGroenten en ODSFiets via de

Toolbox, onderdeel Data. Koppel deze aan de juiste methoden van Logic.Busisness en Logic.Fietsroutes

Meester.master

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="Meester.master.cs" Inherits="Meester" %>

<!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>

ODS in Masterpage<br />

122

Frank Horemans

Page 123: Cursus ASP.net 1

<br /> <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:contentplaceholder> <br /> <asp:ObjectDataSource ID="ODSFiets" runat="server" SelectMethod="GetFietsRoutes" TypeName="Logic.Fietsroutes"></asp:ObjectDataSource> <asp:ObjectDataSource ID="ODSGroenten" runat="server" SelectMethod="GetGroenten" TypeName="Logic.Business"></asp:ObjectDataSource> </div> </form></body></html>

Om vanuit een Childpagina elementen uit een Masterpage te kunnen benaderen zorgen we in de codebehind van de Masterpage voor publieke eigenschappen die deze ObjectDataSources retourneren:

public partial class Meester : System.Web.UI.MasterPage{ public ObjectDataSource OdsFiets { get { return ODSFiets; } }

public ObjectDataSource OdsGroenten { get { return ODSGroenten; } }

...

}

Maak een Web Form Datalist_child met als Masterpage Meester.master Voeg een ListBox LBGroenten en een DataList DLFiets toe op de pagina.

Om eigenschappen van een MasterPage aan te spreken moeten we normaal een vervelende typecasting naar de klasse van de Masterpage uitvoeren telkens we een eigenschap wensen te gebruiken. Dit kunnen we vermijden door in de Child-pagina Datalist_child volgende directive te voorzien onder de Page-directive:

Datalist_child.aspx...<%@ MasterType VirtualPath="~/Meester.master" %>...

Doordat de ObjectDataSources zich niet bevinden op de huidige pagina, maar in de Masterpage, zullen we de DataSource van deze componenten instellen vanuit de code:

DataList_child.aspx.csprotected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { LBGroenten.DataSource = Master.OdsGroenten;

123

Frank Horemans

Page 124: Cursus ASP.net 1

DLFiets.DataSource = Master.OdsFiets; DataBind(); }}

Wens je gebruik te maken van een selectie en deselectie mogelijkheid (en bijbehorende templates) zoals in het voorbeeld, dan moet je ervoor zorgen dat in de eventhandlers de DataSource opnieuw wordt gebonden: deze keer zijn er geen ASP-tags in de child-pagina die voor deze koppeling zorgen. Wanneer een event plaatsvindt moet deze koppeling opnieuw gebeuren.

protected void DLFiets_ItemCommand(object source, DataListCommandEventArgs e){ if (e.CommandName == "unselect") { DLFiets.DataSource = Master.OdsFiets; DLFiets.SelectedIndex = -1; } DLFiets.DataBind();}

protected void DLFiets_SelectedIndexChanged(object sender, EventArgs e){ DLFiets.DataSource = Master.OdsFiets; DLFiets.DataBind();}

11.4 DataList: gegevens editeren

Een DataList kan je ook gebruiken om gegevens uit de Datasource aan te passen.

Om realistischer te werken koppelen we onze Webapplicatie deze keer aan een database. In volgende stapjes maak je een nieuwe SQL Server 2005 Express-database aan met Visual Studio 2005. Werk je liever met SQL Server 2000 / 2005 open dat resp. Enterprise Manager / Management Studio, en maak een nieuwe database aan.

Rechtsklik in Solution Explorer de map app_data van de Web Site. Kies Add Item... Kies SQL Database: Drank.mdf Maak via Server Explorer een tabel drank aan in Drank.mdf

id - int - identity - primary key naam - varchar(50) prijs - money

124

Frank Horemans

Page 125: Cursus ASP.net 1

Geef een aantal voorbeeldwaarden in

Voorzie twee Stored Procedures in de database Drank.mdf:

CREATE PROCEDURE dbo.DrankSelectAS

SET NOCOUNT ON;SELECT id, naam, prijsFROM drankORDER BY naam

GO

CREATE PROCEDURE dbo.DrankUpdate(

@id int,@naam varchar(50),@prijs float

)AS

SET NOCOUNT OFF;UPDATE [drank] SET [naam] = @naam, [prijs] = @prijs WHERE [id] = @id;

Voorzie in Web.config van de site volgende waarde voor de connectiestring:

...<configuration>

<appSettings/><connectionStrings>

<add name="DrankConn" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Drank.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/>

</connectionStrings><system.web>...

In de Class-Library DAL maken we de klasse DrankDB aan:

using System;using System.Collections.Generic;using System.Text;using System.Configuration;using System.Data;using System.Data.SqlClient;

125

Frank Horemans

Page 126: Cursus ASP.net 1

namespace DAL{ public class DrankDB { public static DataSet GetDranken() { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["DrankConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("DrankSelect", myConnection); myCommand.CommandType = CommandType.StoredProcedure; SqlDataAdapter da = new SqlDataAdapter(myCommand); DataSet ds = new DataSet("DsDranken"); da.Fill(ds,"Dranken");

return ds; }

public static void DrankenUpdate(int id, string naam, float prijs) { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["DrankConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("DrankUpdate", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.Add(new SqlParameter("@id", id)); myCommand.Parameters.Add(new SqlParameter("@naam", naam)); myCommand.Parameters.Add(new SqlParameter("@prijs", prijs)); myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close(); } }}

Deze klasse bevat de methoden die werkelijk connectie met de database maken. We retourneren nog geen custom objecten, maar ADO.Net - objecten. Op deze manier moeten we hier geen referentie naar Logic maken en blijft onze DAL onafhankelijk.

Voor het gebruik van ConfigurationManager is het mogelijk dat je nog eens expliciet een referentie moet leggen naar System.Configuration. We gebruiken vanuit de DAL-laag de connectionstring uit de Web.Config van de site, je kan de connectiestring ook in een app.config-file van de DAL-laag opnemen.

In de Class-Library Logic maken we de klassen Drank, Drankcollection en Dranken aan in de file Drank.cs:

Drank.cs

using System;using System.Collections;

126

Frank Horemans

Page 127: Cursus ASP.net 1

using System.Collections.Generic;using System.Text;using System.Data;using DAL;

namespace Logic{ public class Drank {

private int id;

public int Id { get { return id; } set { id = value; } } private string naam;

public string Naam { get { return naam; } set { naam = value; } } private Single prijs;

public Single Prijs { get { return prijs; } set { prijs = value; } }

public Drank() { }

public Drank(int id, string naam, Single prijs) { Id = id; Naam = naam; Prijs = prijs; } }

public class Drankcollection : CollectionBase { public Drankcollection() { }

public void Add(Drank d) { InnerList.Add(d); } //indexer: "Item"-property public Drank this[int index] { get { return (Drank)InnerList[index]; }

127

Frank Horemans

Page 128: Cursus ASP.net 1

set { InnerList[index] = value; } } }

public class Dranken { public static Drankcollection GetDranken() { DataSet ds = DrankDB.GetDranken(); DataTable dt = ds.Tables["Dranken"];

Drankcollection dc = new Drankcollection(); for (int i = 0; i < dt.Rows.Count; i++ ) { Drank d = new Drank(); d.Id = Convert.ToInt32(dt.Rows[i]["id"]); d.Naam = dt.Rows[i]["Naam"].ToString(); d.Prijs = Convert.ToSingle(dt.Rows[i]["Prijs"]); dc.Add(d); } return dc; }

public static void DrankenUpdate(int id, string naam, float prijs) { DrankDB.DrankenUpdate(id, naam, prijs); }

}

}

De methode GetDranken uit de klasse Dranken haalt de gegevens op uit de Datalaag en maakt er Custom Objecten van.

Maak in de website een nieuwe Web Form Datalist_dranken.aspx aan Voorzie een DataList DLdrank Stel de eigenschap DataKeyField in op Id Kies Edit Templates - ItemTemplates:

128

Frank Horemans

Page 129: Cursus ASP.net 1

Voorzie in de Page_Load van Datalist_dranken.aspx

protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind(); }}

Maak een EventHandlers voor de DataList DLdrank:

SelectedIndexChanged (uitgevoerd bij select-command)

protected void DLdrank_SelectedIndexChanged(object sender, EventArgs e){ DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind();}

ItemCommand (voor een willekeurig command - hier unselect)

129

Frank Horemans

Page 130: Cursus ASP.net 1

protected void DLdrank_ItemCommand(object source, DataListCommandEventArgs e){ if (e.CommandName == "unselect") { DLdrank.SelectedIndex = -1; DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind(); }}

EditCommand (uitgevoerd bij edit-command)

protected void DLdrank_EditCommand(object source, DataListCommandEventArgs e){ DLdrank.EditItemIndex = e.Item.ItemIndex; DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind();}

CancelCommand (uitgevoerd bij cancel-command)

protected void DLdrank_CancelCommand(object source, DataListCommandEventArgs e){ DLdrank.EditItemIndex = -1; DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind();}

o

UpdateCommand (uitgevoerd bij update-command)

protected void DLdrank_UpdateCommand(object source, DataListCommandEventArgs e){ DLdrank.EditItemIndex = -1;

int id = Convert.ToInt32(DLdrank.DataKeys[e.Item.ItemIndex]); string naam = ((TextBox)e.Item.FindControl("TxtNaam")).Text; float prijs = Convert.ToSingle(((TextBox)e.Item.FindControl("TxtPrijs")).Text);

Dranken.DrankenUpdate(id, naam, prijs);

DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind(); }

130

Frank Horemans

Page 131: Cursus ASP.net 1

11.5 DataList: items toevoegen

Voorzie een Stored Procedure DrankInsert in Drank.mdf

CREATE PROCEDURE dbo.DrankInsert(

@naam varchar(50),@prijs float,@id int output

)AS

SET NOCOUNT OFF;INSERT INTO [drank] ([naam], [prijs]) VALUES (@naam, @prijs);

Set @id = SCOPE_IDENTITY()

Deze Stored Procedure bevat een outputparameter met het id van het nieuwe drankje. Dit Id zullen we straks tonen in een Label op de Web Form.

Voorzie een methode DrankenInsert in de klasse DAL.DrankDB

public static int DrankenInsert(string naam, float prijs){ SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["DrankConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("DrankInsert", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.Add(new SqlParameter("@naam", naam)); myCommand.Parameters.Add(new SqlParameter("@prijs", prijs)); SqlParameter pid = new SqlParameter("@id", SqlDbType.Int); pid.Direction = ParameterDirection.Output; myCommand.Parameters.Add(pid);

myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close();

int id = Convert.ToInt32(pid.Value);

return id;}

131

Frank Horemans

Page 132: Cursus ASP.net 1

Voorzie een methode DrankenInsert in de klasse Logic.Dranken in Drank.cs

public static int DrankenInsert(string naam, float prijs){ return DrankDB.DrankenInsert(naam, prijs);}

Voorzie in een FooterTemplate voor de DataList DLdrank

o Een TextBox: ID: TxtNaamNew - Width:50px o Een TextBox: ID: TxtPrijsNew - Width:50px o Een ImageButton: ImageUrl: new.jpg - CommandName: insert

Plaats een Label LblMsg onder de DataList, maak de eigenschap Text leeg Voorzie volgende code in de Page_Load van de Web Form:

protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { DLdrank.DataSource = Dranken.getDranken(); DLdrank.DataBind(); }

LblMsg.Text = "";}

Voorzie volgende code in de EventHandler ItemCommand:

protected void DLdrank_ItemCommand(object source, DataListCommandEventArgs e){ ...

if (e.CommandName == "insert") { string naam = ((TextBox)e.Item.FindControl("TxtNaamNew")).Text; float prijs = Convert.ToSingle(((TextBox)e.Item.FindControl("TxtPrijsNew")).Text); DLdrank.SelectedIndex = -1; int id = Dranken.DrankenInsert(naam, prijs); DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind();

LblMsg.Text = "Drank toegevoegd met id " + id; }}

132

Frank Horemans

Page 133: Cursus ASP.net 1

11.6 DataList: items verwijderen

Voorzie een Stored Procedure DrankDelete in Drank.mdf

CREATE PROCEDURE dbo.DrankDelete(

@id int)AS

SET NOCOUNT OFF;DELETE FROM [drank] WHERE [id] = @id

Voorzie in de ItemTemplate en SelectedItemTemplate een ImageButton:

o ImageUrl: images/delete.jpg o CommandName: delete

Voorzie een methode DrankenDelete in de klasse DAL.DrankDB

public static void DrankenDelete(int id){ SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["DrankConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("DrankDelete", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.Add(new SqlParameter("@id", id));

myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close();}

Voorzie een methode DrankenDelete in de klasse Logic.Dranken in Drank.cs

...public static void DrankenDelete(int id){ DrankDB.DrankenDelete(id);}...

Voorzien een EventHandler voor DeleteCommand voor DLdrank:

133

Frank Horemans

Page 134: Cursus ASP.net 1

protected void DLdrank_DeleteCommand(object source, DataListCommandEventArgs e){ int id = Convert.ToInt32(DLdrank.DataKeys[e.Item.ItemIndex]); Dranken.DrankenDelete(id);

DLdrank.DataSource = Dranken.GetDranken(); DLdrank.DataBind();}

134

Frank Horemans

Page 135: Cursus ASP.net 1

12 GRIDVIEW - DETAILSVIEW

1. GridView: voorbereiding en inleiding 2. GridView: data tonen 3. GridView: kolommen 4. GridView: sorteren 5. GridView: pagineren 6. GridView: data editeren 7. GridView: foutafhandeling 8. GridView: data verwijderen 9. GridView: rijen selecteren 10. GridView: gegevens uit een rij tonen 11. GridView: rijen aanpassen 12. DetailsView: detailgegevens tonen 13. DetailsView: gegevens toevoegen 14. DetailsView: gegevens editeren en deleten

12.1 GridView: voorbereiding voor 3-tier toepassing

Het besturingselement GridView is een aan gegevens gebonden raster met meerdere kolommen waarmee je verschillende typen kolommen kan dfiniëren. Deze kolommen voorzien de rasterinhoud niet alleen van een lay-out, maar voegen ook functionaliteit toe om gegevens te selecteren, bewerken, sorteren en pagineren. De GridView biedt ook functionaliteit voor volledige aanpassing van de uitvoer middels het gebruik van sjabloonkolommen.

Je kan een GridView binden aan gegevensbron zoals een database, maar ook aan eenvoudige structuren zoals een ArrayList of aan je eigen collectie van Custom Objecten.

Een DataGrid wordt door de browser gerendered als een Table.

Aangezien we in deze lessenreeks gebruik maken van een gestructureerde onderverdeling in klassen, volgen we verder deze werkwijze.

Kies in de App_Data-map van de Site voor: New Item... - SQL Database - Nascholing.mdf (of maak een nieuwe Database in SQL Server 2000 / 2005)

Maak verbinding met de database via Server Explorer Maak een table nascholing aan:

De id-kolom is een identity-kolom

Voeg een aantal voorbeeldgegevens in:

135

Frank Horemans

Page 136: Cursus ASP.net 1

Maak een Stored Procedure aan:

CREATE PROCEDURE dbo.NascholingSelect AS

Select id, naam, plaats, datum, prijs, actiefFROM nascholingRETURN

Voorzie de connectiestring in Web.Config van de Site

<connectionStrings><add name="DrankConn" providerName="System.Data.SqlClient"

connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Drank.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/> <add name="NascholingConn" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Nascholing.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/>

</connectionStrings>

Maak in de namespace DAL een klasse NascholingDB aan:

using System;using System.Collections.Generic;using System.Text;using System.Data;using System.Data.SqlClient;using System.Configuration;

namespace DAL{ public class NascholingDB { public static DataSet GetNascholingen() { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NascholingConn"].ConnectionString);

SqlCommand myCommand = new SqlCommand("NascholingSelect", myConnection); myCommand.CommandType = CommandType.StoredProcedure;

SqlDataAdapter da = new SqlDataAdapter(myCommand);

DataSet ds = new DataSet("DsNascholing");

136

Frank Horemans

Page 137: Cursus ASP.net 1

da.Fill(ds, "Nascholingen");

return ds; } }}

Maak in de namespace Logic Nascholing.cs aan:

using System;using System.Collections.Generic;using System.Text;using System.Collections;using System.Data;using DAL;

namespace Logic{ public class Nascholing { private int id;

public int Id { get { return id; } set { id = value; } } private string naam;

public string Naam { get { return naam; } set { naam = value; } } private string plaats;

public string Plaats { get { return plaats; } set { plaats = value; } } private DateTime datum;

public DateTime Datum { get { return datum; } set { datum = value; } } private Decimal prijs;

public Decimal Prijs { get { return prijs; } set { prijs = value; } } private Boolean actief;

public Boolean Actief

137

Frank Horemans

Page 138: Cursus ASP.net 1

{ get { return actief; } set { actief = value; } }

public Nascholing() { } }

public class Nascholingcollection : CollectionBase { public Nascholingcollection() { }

public void Add(Nascholing n) { InnerList.Add(n); }

//indexer: "Item"-property public Nascholing this[int index] { get { return (Nascholing)InnerList[index]; } set { InnerList[index] = value; } } }

public class Nascholingen { public static Nascholingcollection GetNascholingen() { DataSet ds = NascholingDB.GetNascholingen(); DataTable dt = ds.Tables["Nascholingen"];

Nascholingcollection nc = new Nascholingcollection(); for (int i = 0; i < dt.Rows.Count; i++) { Nascholing d = new Nascholing(); d.Id = Convert.ToInt32(dt.Rows[i]["id"]); d.Naam = dt.Rows[i]["naam"].ToString(); d.Plaats = dt.Rows[i]["plaats"].ToString(); d.Datum = Convert.ToDateTime(dt.Rows[i]["datum"]); d.Prijs = Convert.ToDecimal(dt.Rows[i]["prijs"]); d.Actief = Convert.ToBoolean(dt.Rows[i]["actief"]); nc.Add(d); } return nc; } }}

138

Frank Horemans

Page 139: Cursus ASP.net 1

12.2 Gridview: gegevens tonen

12.2.1.1 Handmatig binden aan Business object

In dit voorbeeld doen we het binden van de gegevens aan de GridView handmatig: in de methode Page_Load van de pagina stellen we de custom collectie met nascholingen in als DataSource van de GridView.

Maak in de Site een nieuwe Web Form: Gridview_nascholing.aspx Sleep een GridView op de Web Form: GVnascholing Geef als Auto format "Sand & Sky" Voorzie in Gridview_nascholing.aspx.cs

...using Logic;

public partial class Gridview_nascholing : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { GVnascholing.DataSource = Nascholingen.GetNascholingen(); GVnascholing.DataBind(); } }}

12.2.1.2 Met een ObjectDataSource

Werk je met een ObjectDataSource, dan hoef je het binden van de data aan de GridView niet meer zelf te doen in de code. Vanzelfsprekend kan je de ObjectDataSource ook voorzien van insert, update en delete-functionaliteiten (door de achterliggende klassen aan te passen en de data source aan te passen) om aldus deze acties vanuit de GridView te kunnen uitvoeren.

139

Frank Horemans

Page 140: Cursus ASP.net 1

Sleep een GridView GVnascholingODS op de Web Form Geef als Auto Format "Rainy Day" Via smart tags kies je voor Choose Datasource: New Data Source Kies Object als Data Source type Geef als naam ODSnascholing op Logic.Nascholingen is het Business object GetNascholingen is de select-methode

12.2.1.3 Met een SqlDataSource

Dit is de quick & dirty manier van werken: je koppelt de GridView rechtstreeks aan de SQL-Database. DAL en LOGIC uit onze toepassing worden hier niet gebruikt.

Plaats een GridView GVnascholingSDS op de Web Form Geef als Auto Format "Autumn" Via smart tags kies je voor Choose Datasource: New Data Source Kies Database als Data Source type Geef als naam SDSnascholing op Kies NascholingConn als Data Connection (de connectiestring in Web.config)

We werken met onze eigen Stored Procedure

140

Frank Horemans

Page 141: Cursus ASP.net 1

We hebben een Stored Procedure voorzien voor het selecteren van de record. Als je reeds update, insert en delete-procedures hebt gemaakt kan je deze nu koppelen aan de GridView, dit kan later ook via Configure Data Source van de GridView.

141

Frank Horemans

Page 142: Cursus ASP.net 1

Test de Stored Procedure en druk op Finish.

142

Frank Horemans

Page 143: Cursus ASP.net 1

12.2.1.4 Met een typed DataSet en automatisch gegenereerde Stored Procedures

Deze keer maken we eerste een typed DataSet aan en binden we de GridView aan een TableAdapter van de DataSet. Het grote voordeel van deze werkwijze is dat je Visual Studio 2005 de opdracht kan geven om Stored Procedures (of ingebedde SQL) automatisch voor jou aan te maken. Deze manier van werken stelt je echt in staat aan RAD (Rapid Application Development) te doen. Opgepast, onze eigen DAL en LOGIC-laag worden hier niet meer gebruikt.

Voeg een nieuw item toe aan de site: DataSet: DSnascholing Accepteer het voorstel om de DataSet in de App_Code map te plaatsen Kies NascholingConn als Data Connectie

143

Frank Horemans

Page 144: Cursus ASP.net 1

We laten de Stored Procedures door Visual Studio aanmaken.

We zijn heel erg lui en kiezen de Query Builder om de Select Stored Procedure te genereren.

144

Frank Horemans

Page 145: Cursus ASP.net 1

Voeg de tabel nascholing toe aan de Query Builder

145

Frank Horemans

Page 146: Cursus ASP.net 1

Gebruik alle velden en sorteer oplopend op naam

Via advanced options geef je aan dat je de Insert, Update en Delete Statements wenst aan te maken.

146

Frank Horemans

Page 147: Cursus ASP.net 1

Geef de Stored Procedures een naam

147

Frank Horemans

Page 148: Cursus ASP.net 1

Geef aan welke methoden er voor de TableAdapter aangemaakt moeten worden

148

Frank Horemans

Page 149: Cursus ASP.net 1

Hiep hiep hoera, enkel nog op finish drukken...

Plaats een GridView GVnascholingDS op de Web Form Geef als Auto Format "Oceanica" Via smart tags kies je voor Choose Datasource: New Data Source Kies Object als Data Source type Geef als naam ODSnascholingDS op

149

Frank Horemans

Page 150: Cursus ASP.net 1

Kies de TableAdapter uit de DataSet als Data Source

De methoden voor Select, Update, Insert en Delete werden netjes aan de ObjectDataSource gekoppeld!

150

Frank Horemans

Page 151: Cursus ASP.net 1

12.2.1.5 Een keuze maken uit de verschillende methoden

We hebben nu 4 manieren gezien om een GridView te binden aan een DataSource. Deze manieren kan je ook toepassen voor andere DataControls.

Welke manier moet je nu gebruiken in je toepassingen?

o De grootste flexibiliteit heb je bij het manueel koppelen aan je eigen methoden uit bvb. de Logische laag van je applicatie: je hebt alle code zelf in beheer en kan ingrijpen waar nodig. Deze manier van werken is echter het meest arbeidsintensief en vereist een grondige kennis van de achterliggende principes. Deze manier van werken is eigenlijk enkel aan te raden wanneer je enkel gegevens wenst te tonen in de applicatie. Om te sorteren en te pagineren moet je zelf je klassen en stored procedures aanpassen.

o Een goede middenweg tussen RAD en onderhoudbare en flexibele code is het werken met een ObjectDataSource. Het maken van klassen en Stored Procedures blijft volledig je eigen taak. Naar sortering toe heb je wel nog wat extra werk voor de boeg.

o Snel snel iets maken kan gebeuren via de SqlDataSource, als de stored procedures er al zijn, en je wenst vlug resultaat in je applicatie is dit de manier om te werken. Daar alle code deel uitmaakt van je aspx-source is het wel niet geschikt voor

151

Frank Horemans

Page 152: Cursus ASP.net 1

onderhoudsintensieve toepassingen, en strookt het niet met de principes voor herbruikbare code.

o Een weg die momenteel heel vaak wordt bewandeld is die van de Typed DataSet. Daar Visual Studio voor jou een DataSet met de nodige Eigenschappen en methoden kan aanmaken is dit een heel aanvaarbare oplossing. Eigenlijk maakt VS voor jou de DataAccess-layer. Dit is dan misschien een nadeel: je eigen klassen zijn niet meer de herbruikbare componenten, maar je werkt met een automatisch gecreëerde DataSet. Deze manier werkt gerbuikt dus ook een ObjectDataSource, maar deze keer gekoppeld aan een gegenereerde DataSet in plaats van aan onze eigen Logische- of datalaag. Per resultaattabel wordt dan ook een TableAdapter aangemaakt die alle nodige acties ter beschikking stelt. Daar deze weg op volautomische en toch gestructureerde manier toegang verleent tot data-objecten is het veelal een goede keuze. Daar deze manier van werken heel gebruiksvriendelijk is voor verder acties naar selecteren, sorteren en pagineren toe zullen we dit straks wat verder uitdiepen. Als nadeel kan wel geopperd worden dat het werken met een DataSet voor grotere toepassing performatieverlies kan geven.

12.3 GridView: kolommen definiëren

In bovenstaande voorbeelden hebben we telkens gegevens in een GridView geplaatst door eenvoudigweg de GridView te binden aan een DataSource. De GridView werd automatisch gevuld met gegevens en op de webpagina getoond. Je wil natuurlijk de bestaande kolommen aanpassen en eventueel aanvullen. Dit kunnen we allemaal regelen met onze editor Visual Studio 2005 of natuurlijk in de source-code van het aspx-bestand. Kies je via de smart tag van de GridView voor Edit Columns... dan krijg je een dialoogvenster te zien waar je de kolommen van de GridView kan instellen:

152

Frank Horemans

Page 153: Cursus ASP.net 1

Vanuit deze editor kan je kolommen toevoegen, verwijderen en aanpassen. De verschillende kolomtypes:

kolomtype omschrijving

BoundField Standaard type: toont de waarde van een veld als gewone tekst

Buttonfield Toont de waarde van een veld als een CommandButton (linkbutton of push-button)

CheckBoxField Toont de waarde van een veld als CheckBox, veelal gebruikt bij Boolean waarden

CommandFieldGeavanceerde versie van Buttonfield, representeert een speciaal command zoals select, insert, delete, update; zelden gebruikt bij GridView.

153

Frank Horemans

Page 154: Cursus ASP.net 1

HyperLinkField Toont de veldwaarde als een hyperlink, bij klikken surf je naar de gekoppelde pagina

ImageField Toont de waarde van een veld als src-attribuut van een IMG-tag

TemplateField Toont eigen gedefiëerde inhoud voor een kolom. De inhoud kan literals, velden of andere controls bevatten

12.3.1.1 Voorbeeld

We werken met de GridView gebaseerd op de DataSet

Maak de id-kolom onzichtbaar door de eigenschap visible op false te plaatsen Geef de Datumkolom een formatstring: {0:dd/MM/yyyy}

Zet voor deze BoundColumn het attribuut htmlencode op false (kan via het dialoogvenster):

<asp:BoundField DataField="datum" DataFormatString="{0:dd/MM/yyyy}" HeaderText="datum" SortExpression="datum" HtmlEncode="False" />

Door htmlencodering worden tekens zoals "/" omgezet, waardoor de DataFormatString niet meer naar behoren functioneert voor een datumveld.

Zet voor de prijs htmlencode op false en DataFormatString op {0:c} Voeg een TemplateField toe (TemplateField selecteren in bovenste lijst en

drukken op Add) voor 10% korting

o HeaderText: korting o Via smart tag van de GridView kies je edit templates: Column[5] - korting:

ItemTemplate o Voeg een Label toe: edit Databindings: Text: (Convert.ToDouble(Eval("prijs")) *

0.9).ToString("c")

De TemplateField is de krachtigste kolom en staat je toe zelf een opmaak te definiëren voor een aantal varianten zoals AlternatingItem en EditItem

154

Frank Horemans

Page 155: Cursus ASP.net 1

12.4 GridView: kolommen sorteren

12.4.1.1 Codeless sorteren met de Typed DataSet

Via smart tag van de Gridview zet je enable sorting aan Je kan het sorteren op de kortingskolom (TemplateField) ook mogelijk maken door deze

kolom te editeren en de eigenschap sortexpression in te stellen op het veld prijs

Deze vorm van sorteren werkt zonder code te schrijven, maar wordt volledig aan de hand van de ViewState berekend door de webserver.

12.4.1.2 Sorteren door de database-engine

Voor databasetoepassingen met behoorlijk wat records is het soms beter enig rekenwerk zoals sorteren over te laten aan de databaseserver in plaats van het door de webserver te laten doen.

Voorzie in nascholing.mdf een nieuwe Stored Procedure:

CREATE PROCEDURE dbo.nascholingSelectSort@SortBy varchar(50) = 'naam'

ASSET NOCOUNT ON;IF @SortBy = ''BEGIN

SET @SortBy = 'naam'END

EXEC( 'SELECT id, naam, plaats, datum, prijs, actief ' +'FROM nascholing ' +'ORDER BY ' +@SortBy)

Hier gebruiken we een exec voor het uitvoeren van de SQL omdat SQL server anders van zijn oren maakt wanneer je een variabele gebruikt als ORDER BY component.

155

Frank Horemans

Page 156: Cursus ASP.net 1

Voeg een DataSet DSnascholing_dbactie toe in de App_Code folder Kies ervoor om bestaande Stored Procedures te gebruiken:

Dit is het schema van de gemaakte DataTable met TableAdapter:

Pas de ObjectDataSource op de webpagina aan zodat het Business object verwijst naar de nieuwe TableAdapter, de selectmethode is GetData en ontvangt de string

156

Frank Horemans

Page 157: Cursus ASP.net 1

SortBy.

Zeg nee als gevraagd wordt de kolommen van de GridView te resetten

12.4.1.3 Sorteren met de ObjectDataSource

Als je niet met een Typed DataSet werkt, maar met een eigen DAL en eventueel Logic-layer, dan kan je ook sortering voorzien wanneer je bvb. met een ObjectDataSource werkt.

De sortering die we hier voorzien gebeurt op de database.

We gebruiken opnieuw de Stored Procedure NascholingSelectSort die we zopas hebben gemaakt

Voorzie volgende methode in de DAL-library:

157

Frank Horemans

Page 158: Cursus ASP.net 1

NascholingDB.cspublic static DataSet GetNascholingenSorted(string sortby) { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NascholingConn"].ConnectionString);

SqlCommand myCommand = new SqlCommand("NascholingSelectSort", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.AddWithValue("@SortBy", sortby);

SqlDataAdapter da = new SqlDataAdapter(myCommand);

DataSet ds = new DataSet("DsNascholing"); da.Fill(ds, "Nascholingen");

return ds; }

Voorzie volgende methode in de Logic-library:

[DataObjectMethod(DataObjectMethodType.Select)]public static Nascholingcollection GetNascholingenSorted(string sortby) { DataSet ds = NascholingDB.GetNascholingenSorted(sortby); DataTable dt = ds.Tables["Nascholingen"];

Nascholingcollection nc = new Nascholingcollection(); for (int i = 0; i < dt.Rows.Count; i++) { Nascholing d = new Nascholing(); d.Id = Convert.ToInt32(dt.Rows[i]["id"]); d.Naam = dt.Rows[i]["naam"].ToString(); d.Plaats = dt.Rows[i]["plaats"].ToString(); d.Datum = Convert.ToDateTime(dt.Rows[i]["datum"]); d.Prijs = Convert.ToDecimal(dt.Rows[i]["prijs"]); d.Actief = Convert.ToBoolean(dt.Rows[i]["actief"]); nc.Add(d); } return nc; }

Voorzie op een nieuwe Web Form een GridView Kies een Auto Format "Lilacs in mist" Via Choose Data Source kies je New Data Source Object DataSource met als Business object Logic.Nascholingen Select methode: GetNascholingenSorted(string sortby) Als DefaultValue voor de SelectParameter sortby geef je naam op Via de eigenschappen van de ObjectDataSource stel je SortParameterName in op

sortby Activeer Enable sorting via de smart tag van de GridView! Doe nog wat aanpassingen aan de kolommen van de GridView voor een ordelijke

layout (volgorde, DataFormatString).

158

Frank Horemans

Page 159: Cursus ASP.net 1

12.4.1.4 Sorteerorde tonen

Het aanduiden van de sorteervolgorde zorgt voor de gebruiker voor een grotere duidelijkheid.

Dit kunnen we eenvoudig doen door ervoor te zorgen dat het juiste tekeningetje wordt toegevoegd aan de kolom waarop werd gesorteerd. Dit tekeningetje (driehoekje) is eigenlijk een letter uit het lettertype webdings: hierin vinden we een driehoekje met top boven en eentje met top onder.

We plaatsen het driehoekje in de hoofdingkolom nadat een rij uit de grid werd aangemaakt:

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.Header) AddSorteerDriehoek(GridView1, e.Row); }

De methode AddSorteerDriehoek:

void AddSorteerDriehoek(GridView grid, GridViewRow item) { Label driehoek = new Label(); driehoek.EnableTheming = false; driehoek.Font.Name = "webdings"; driehoek.Font.Size = FontUnit.Small; driehoek.Text = (grid.SortDirection == SortDirection.Ascending ? "5" : "6");

for (int i = 0; i < grid.Columns.Count; i++) { string colExpr = grid.Columns[i].SortExpression; if (colExpr != "" && colExpr == grid.SortExpression) item.Cells[i].Controls.Add(driehoek); } }

159

Frank Horemans

Page 160: Cursus ASP.net 1

12.5 GridView: pagineren

12.5.1.1 Pagineren

Pagineren stelt je in staat om slechts een gedeelte van de aanwezige records op het scherm te tonen. ASP.Net zorgt er automatisch voor dat de gebruiker naar een andere resultaatpagina kan overschakelen.

12.5.1.2 Standaard pagineren

Werk je met een GridView gekoppeld aan een typed DataSet, dan kan je paginering inschakelen via de smart tag of properties van de GridView.

Standaard pagineren gaat als volgt in het werk: de webserver leest alle records voor het vullen van bvb. een DataTable in het geheugen en plaatst enkel de benodigde records in de GridView. Wanneer je naar een andere pagina overstapt, worden opnieuw alle records gelezen en de gewenste door de webserver uitgefilterd. Behoorlijk intensief voor de webserver dus. Heb je een tabel met 1000 record en pagina's van 10 records, dan zijn er in totaal 100 pagina's. Als de gebruiker ze allemaal eens bezoekt worden dan eigenlijk in totaal 100 * 1000 records ingelezen (=100.000 records!), terwijl er slechts 1000 getoond worden.

Standaard paginering is heel interessant doordat het weinig extra werk levert voor de ontwikkelaar, voor toepassingen met een kleine database (tientallen tot honderden records) is dit een aanvaardbare oplossing.

Voor het illustreren van paginerig werden in de nascholingstabel een aantal records toegevoegd.

Plaats AllowPaging op true Plaats PageSize op 5

160

Frank Horemans

Page 161: Cursus ASP.net 1

12.5.1.3 Standaard pagineren - veel records

Voor een realistischer voorbeeld, en een vergelijk tussen standaard en custom pagineren gebruiken we een database met enkele duizenden records. In de database Movie.mdf vinden we een tabel movie met een kleine 2.000 recors en een tabel casting met zo'n 30.000 records. Plaats deze database in de App_Data map van je Site.

Voorzie een connectiestring in Web.config

<connectionStrings><add name="DrankConn" providerName="System.Data.SqlClient"

connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Drank.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/> <add name="NascholingConn" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Nascholing.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/> <add name="MovieConn" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Movie.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"/>

</connectionStrings>

We maken een stored procedure die de verschillende films toont en doen een join met de casting-tabel om de intensiteit van de bewerking op te drijven.

CREATE PROCEDURE dbo.SelectAllMovie AS

161

Frank Horemans

Page 162: Cursus ASP.net 1

SELECT DISTINCT m.filmid, titel, jaar, scoreFROM

movie m--vertrager: enkel om de query extra intensief te makenINNER JOIN casting c on m.filmid = c.filmid

We voorzien een Class-file MovieDB.cs in de DAL-library, voor de standaardpaginering gebruiken we de methode MovieDB.SelectAllMovie die een DataSet retourneert met de filmgegevens.

using System;using System.Collections.Generic;using System.Text;using System.Data;using System.Data.SqlClient;using System.Configuration;

namespace DAL{ public class MovieDB { private static string connstring = ConfigurationManager.ConnectionStrings["MovieConn"].ConnectionString;

public static DataSet SelectAllMovie() { SqlConnection myConnection = new SqlConnection(connstring);

SqlCommand myCommand = new SqlCommand("SelectAllMovie", myConnection); myCommand.CommandType = CommandType.StoredProcedure;

SqlDataAdapter da = new SqlDataAdapter(myCommand);

DataSet ds = new DataSet("DsMovie"); da.Fill(ds, "Movies"); int aantal = ds.Tables["Movies"].Rows.Count; return ds; }

public static DataSet SelectMovie(string sortby, int startrij, int aantalrijen) { SqlConnection myConnection = new SqlConnection(connstring);

SqlCommand myCommand = new SqlCommand("SelectMovie", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.AddWithValue("@sortby", sortby); myCommand.Parameters.AddWithValue("@startrij", startrij); myCommand.Parameters.AddWithValue("@aantalrijen", aantalrijen);

SqlDataAdapter da = new SqlDataAdapter(myCommand);

DataSet ds = new DataSet("DsMovie");

162

Frank Horemans

Page 163: Cursus ASP.net 1

da.Fill(ds, "Movies"); int aantal = ds.Tables["Movies"].Rows.Count; return ds; }

public static int CountMovie() { SqlConnection myConnection = new SqlConnection(connstring);

SqlCommand myCommand = new SqlCommand("CountMovie", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myConnection.Open(); int aantalfilms = Convert.ToInt32(myCommand.ExecuteScalar()); myConnection.Close(); return aantalfilms; } }}

We zorgen nu ook voor een extra file Movie.cs in de Logic-laag:

using System;using System.Collections.Generic;using System.Text;using System.Data;using System.Collections;using System.ComponentModel;using DAL;

namespace Logic{ public class Movie { private int id;

public int Id { get { return id; } set { id = value; } } private string titel;

public string Titel { get { return titel; } set { titel = value; } } private int jaar;

public int Jaar { get { return jaar; } set { jaar = value; } }

163

Frank Horemans

Page 164: Cursus ASP.net 1

private float score;

public float Score { get { return score; } set { score = value; } }

public Movie() { } }

public class Moviecollection : CollectionBase { public Moviecollection() { }

public void Add(Movie m) { InnerList.Add(m); }

//indexer: "Item"-property public Movie this[int index] { get { return (Movie)InnerList[index]; } set { InnerList[index] = value; } } }

[DataObject] public class Movies {

[DataObjectMethod(DataObjectMethodType.Select)] public static Moviecollection SelectAllMovie() { DataSet ds = MovieDB.SelectAllMovie(); DataTable dt = ds.Tables["Movies"];

Moviecollection col = new Moviecollection(); for (int i = 0; i < dt.Rows.Count; i++) { Movie o = new Movie(); o.Id = Convert.ToInt32(dt.Rows[i]["FilmID"]); o.Titel = dt.Rows[i]["Titel"].ToString(); o.Jaar = Convert.ToInt32(dt.Rows[i]["Jaar"]); o.Score = Convert.ToSingle(dt.Rows[i]["Score"]); col.Add(o); } return col; }

[DataObjectMethod(DataObjectMethodType.Select)] public static Moviecollection SelectMovie(string sortby, int startrij, int aantalrijen) {

164

Frank Horemans

Page 165: Cursus ASP.net 1

DataSet ds = MovieDB.SelectMovie(sortby, startrij, aantalrijen); DataTable dt = ds.Tables["Movies"];

Moviecollection col = new Moviecollection(); for (int i = 0; i < dt.Rows.Count; i++) { Movie o = new Movie(); o.Id = Convert.ToInt32(dt.Rows[i]["FilmID"]); o.Titel = dt.Rows[i]["Titel"].ToString(); o.Jaar = Convert.ToInt32(dt.Rows[i]["Jaar"]); o.Score = Convert.ToSingle(dt.Rows[i]["Score"]); col.Add(o); } return col; }

[DataObjectMethod(DataObjectMethodType.Select)] public static int CountMovie(string sortby, int startrij, int aantalrijen) { return MovieDB.CountMovie(); } }}

Op een nieuwe Web Form plaats je een GridView

Kies een Auto Format o Via Choose Data Source kies je New Data Source o Maak een ObjectDataSource naar Logic.Movies o De SelectMethode is Logic.SelectAllMovie o Allowpaging van de GridView zet je op true

Plaats een Label Label1 op de Web Form, met lege eigenschap Text Voorzie eventhandlers in de code-behind om de tijdsduur van het pagineren te

berekenen.

using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;

public partial class GridView_standardpaging : System.Web.UI.Page{ DateTime starttijd;

165

Frank Horemans

Page 166: Cursus ASP.net 1

protected void Page_Load(object sender, EventArgs e) { starttijd = System.DateTime.Now; }

protected void GridView2_DataBound(object sender, EventArgs e) { DateTime eindtijd = System.DateTime.Now; Label1.Text = ((TimeSpan)(eindtijd - starttijd)).TotalMilliseconds.ToString(); }}

12.5.1.4 Custom pagineren

Het is nu de bedoeling de webserver te ontlasten, en enkel de benodigde records uit de database te lezen.

Maak twee nieuwe Stored Procedures in Movie.mdf

CREATE PROCEDURE dbo.SelectMovie

(@sortby varchar(100) = 'titel',@startrij int = 1,@aantalrijen int = 10)

ASSELECT filmid, titel, jaar, scoreFROM

(SELECT m.filmid, titel, jaar, score, ROW_NUMBER() OVER(ORDER BY @sortby) as RowNum

166

Frank Horemans

Page 167: Cursus ASP.net 1

FROM movie m -- voor de lol, om het trager te maken!! INNER JOIN casting c on m.filmid = c.filmid

) as volgordeWHERE RowNum BETWEEN @startrij AND (@startrij + @aantalrijen) - 1

CREATE PROCEDURE dbo.CountMovieAS

select count(*) from movie

De Stored Procedure SelectMovie maakt gebruik van de nieuwe SQL Server 2005 functie ROW_NUMBER() om elke rij een oplopend nummer te geven en op een eenvoudige manier welbepaalde records uit de tabel te halen. Meer hierover bij 4GuysFromRolla.

Maak een nieuwe Web Form aan Plaats een GridView op de Web Form Kies een Auto Format Via smart tag kies je voor Choose Data Source - New Data Source

o Business object: Logic.Movies o Select Method: SelectMovie(string sortby, Int32 startrij, Int32 aantalrijen) returns

MovieCollection

Eigenschappen van de ObjectDataSource:

o SortParameterName: sortby o EnabelPaging: true o MaximumRowsParameterName: aantalrijen o SelectCountMethod: CountMovie o StartRowIndexParameterName: startrij

Eigenschappen van de GridView: EnablePaging: true Plaats ook een Label en analoge eventhandlers als in de vorige toepassing voor het

tonen van de bewerkingstijd.

12.6 GridView: Data editeren

Met een GridView is het ook mogelijk om de gebruiker toe te staan om de gegevens in de GridView aan te passen en de nieuwe waarden weg te schrijven in de onderliggende Data Source.

167

Frank Horemans

Page 168: Cursus ASP.net 1

12.6.1.1 Typed DataSet

Plaats een GridView op een Web Form... Kies een Auto format Kies via smart tag voor Choose Data Source - New Data Source Maak een ObjectDataSource door gebruik te maken van

DSnascholingTableAdapters.nascholingTableAdapter als Business object (DataSet DSnascholing werd eerder in dit hoofdstuk aangemaakt)

Deze DataSet werkt met Stored Procedures die door de Visual Studio Wizard werden aangemaakt.

Zet via smart tag Enable Editing van de GridView aan Via smart tag > Edit columns plaats je de eigenschap ReadOnly voor de kolom id

op false, zie verder. Voer uit!

Het aanvinken van de optie Enable editing zorgt ervoor dat automatisch een CommandField-kolom wordt aangemaakt met een LinkButton Edit, wanneer je deze aanklikt kom je voor deze rij in editeermodus en zie je de LinkButtons Update en Cancel.

Werk je met een Typed DataSet als Data Source voor de ObjectDataSource, dan is editeren van records enkel een kwestie van het aanvinken van "enable editing" via de smart tag van de GridView.

Er is wel een heel vervelend probleem voor updaten van gegevens, dat een foutmelding 'Could not find a non-generic method "Update"...' wordt gegeven.

Dit is in ons geval opgelost door voor de id-kolom de eigenschap ReadOnly op false in te stellen. Niet echt elegant, maar wel een oplossing.

Dit probleem heeft te maken met de DataTableAdapter Wizard bij het maken van een DataSet die een stored procedure en methode voor Updaten aanmaakt die een id en een original_id gebruikt, terwijl de GridView deze niet allebei retourneert wanneer id een primary key-veld is, de GridView gaat er vanuit dat het id alleen-lezen is en geeft het originele id niet mee, terwijl de Wizard die de Stored Procedures, TableAdapter en methoden heeft aangemaakt ervan uitgaat dat het primaire sleutelveld wel kan worden gewijzigd.

168

Frank Horemans

Page 169: Cursus ASP.net 1

12.6.1.2 Typed DataSet - eigen Stored Procedure

De Stored Procedures die werden aangemaakt door de DataSet-Wizard van Visual Studio zijn handig, maar veelal zal je zelf reeds een Stored Procedure voor gegevensupdate aangemaakt hebben.

Maak in nascholing.mdf een nieuwe Stored Procedure:

CREATE PROCEDURE dbo.NascholingUpdate(

@id int,@naam varchar(50),@plaats varchar(50),@datum datetime,@prijs money,@actief bit

)AS

SET NOCOUNT OFF;UPDATE nascholing SET

naam = @naam,plaats = @plaats, datum = @datum, prijs = @prijs, actief = @actief

WHERE id = @id;

Voeg aan de map App_Code een nieuwe DataSet DSnascholing_eigenSTP toe Kies voor het gebruiken van eigen Stored Procedures

169

Frank Horemans

Page 170: Cursus ASP.net 1

Plaats een GridView op een Web Form Kies een Auto Format Kies via Choose Data Source voor New Data Source... Maak een ObjectDataSource met

DSNascholing_eigenSTPTableAdapters.nascholingSelectSortTableAdapter als Business object

Via de source van de aspx-pagina pas je de code van de ObjectDataSource aan: verwijder het attribuut OldValuesParameterFormatString="original_{0}" of verander dit in OldValuesParameterFormatString="{0}", de ObjectDataSource-Wizard gaat ervan uit dat de updatemethode en de stored procedure een parameter original_id zal bevatten, wat bij ons niet zo is.

12.6.1.3 Een eigen ObjectDataSource in 3-tier toepassing

Wanneer je zelf een DataAccess- en eventueel een Logic-layer hebt gemaakt voor je toepassing, dan kan je een ObjectDataSource aanmaken die jouw methoden gebruikt.

Voeg een methode toe in de DAL-laag, de stored procedure NascholingUpdate werd reeds eerder aangemaakt:

NascholingDB.cs...

public static void Update(int id, string naam, string plaats, DateTime datum, decimal prijs, bool actief)

170

Frank Horemans

Page 171: Cursus ASP.net 1

{ SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NascholingConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("NascholingUpdate", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.AddWithValue("@id", id); myCommand.Parameters.AddWithValue("@naam", naam); myCommand.Parameters.AddWithValue("@plaats", plaats); myCommand.Parameters.AddWithValue("@datum", datum); myCommand.Parameters.AddWithValue("@prijs", prijs); myCommand.Parameters.AddWithValue("@actief", actief);

myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close(); }...Voeg een methode toe aan de Logic-laag: Nascholing.cs...

[DataObjectMethod(DataObjectMethodType.Update)] public static void Update(Nascholing n) { NascholingDB.Update(n.Id, n.Naam, n.Plaats, n.Datum, n.Prijs, n.Actief); }...

Voeg een GridView toe aan een Web Form Kies een Auto Format Kies choose Data Source - New Data Source Maak een ObjectDataSource Business object: Logic.Nascholingen Selectmethode: GetNascholingenSorted Updatemethode: Update Via de eigenschappen van de ObjectDataSource stel je de SortParameterName in

op sortby (om sorteren te voorzien) Enable sorting en editing van de GridView Daar wij een DateTime veld hebben voorzien krijgen we nu een fout bij omzetting

van DateTime naar string.

Om dit op te lossen moeten we handmatig een UpdateParameter-lijst voorzien waarbij we expliciet opgeven dat de datum van het type DateTime is:

In de source code van de aspx-file:

...<asp:ObjectDataSource ID="ODSnascholing_3tier" runat="server" DataObjectTypeName="Logic.Nascholing" OldValuesParameterFormatString="original_{0}" SelectMethod="GetNascholingenSorted" SortParameterName="sortby" TypeName="Logic.Nascholingen" UpdateMethod="Update">

171

Frank Horemans

Page 172: Cursus ASP.net 1

<SelectParameters> <asp:Parameter DefaultValue="naam" Name="sortby" Type="String" /> </SelectParameters> <UpdateParameters> <asp:Parameter Name="id" Type="Int32" /> <asp:Parameter Name="naam" Type="String" /> <asp:Parameter Name="plaats" Type="String" /> <asp:Parameter Name="prijs" Type="Decimal" /> <asp:Parameter Name="datum" Type="DateTime" /> <asp:Parameter Name="actief" Type="Boolean" /> </UpdateParameters></asp:ObjectDataSource>...

Je kan dit ook instellen via de eigenschap UpdateParameters van de ObjectDataSource, klikken op '...' toont je een dialoogvenster, kies voor Show advanced properties. Voeg alle inputparameters toe, geef het juiste Type aan.

o Belangrijke vaststelling: onze eigen methode Update ontvangt een object van de klasse Nascholing, de ObjectDataSource van ASP.Net is dus zelfstandig in staat om aan de hand van de opgegeven parameters een correct object aan te maken. Je mag ook een UpdateMethod maken die alle parameters afzonderlijk opvangt.

Foutafhandeling

Om mogelijke invoerfouten van de gebruiker af te handelen zijn er binnen ASP.Net een aantal mogelijkheden.

Fouten afhandelen in de DAL onderscheppen en doorgeven aan de GUI Fouten in een Business (Logic) laag onderscheppen en doorgeven aan de GUI Fouten afhandelen in de GUI-laag door bvb. gebruik te maken van Input Validation Controls.

172

Frank Horemans

Page 173: Cursus ASP.net 1

Fouten afhandelen vooraleer de info wordt doorgegeven aan Logic of Businesslaag, en eventueel waarden aanpassen of de actie annuleren.

De eerste drie mogelijkheden komen verderop in de cursus aan bod, voorlopig zullen we fouten onderscheppen vooraleer we proberen de Data Source te benaderen.

Om op een correcte manier fouten te kunnen afhandelen is het essentiëel te weten hoe gegevens worden doorgegeven van de GridView naar de ObjectDataSource en naar de Logic-laag of DAL.

1. Wannneer de gebruiker waarden editeert klikt hij op een Control met het update-command (in vele gevallen automatisch gegenereerd via enable editing).

2. Het RowUpdating event van de GridView wordt geraised 3. De GridView vult de set UpdateParameters van de ObjectDataSource 4. De GridView start de UpdateMethod van de ObjectDataSource 5. Het event Updating van de ObjectDataSource wordt geraised 6. De ObjectDataSource start de UpdateMethode uit de onderliggende Business-laag of DAL 7. Het event Updated van de ObjectDataSource wordt geraised 8. Het event RowUpdated van de GridView wordt geraised

Wensen we op het niveau van de GridView in te grijpen in de code, dan kunnen we dit in het RowUpdating event gaan doen

We werken verder met de laatst GridView uit het voige onderdeel: GridView gekoppeld aan een ObjectDataSource, ObjectDataSource gebonden aan ons eigen klassenmodel.

Voeg een Label LblMsg toe aan de Web Form, rode tekstkleur, geen tekst. Voorzie een eventhandler voor het event RowUpdating

protected void GridView2_RowUpdating(object sender, GridViewUpdateEventArgs e) { string oudenaam = e.OldValues["Naam"].ToString(); bool updateok = true;

if (e.NewValues["Naam"] == null) { updateok = false; } else { if (e.NewValues["Naam"].ToString().Trim() == "") updateok = false; }

if (!updateok) { LblMsg.Text = "Gelieve een naam op te geven, deze was oorsponkelijk " + oudenaam; e.Cancel = true; }

173

Frank Horemans

Page 174: Cursus ASP.net 1

}

Het berichtlabel heeft standaard een lege tekst:

protected void Page_Load(object sender, EventArgs e) { LblMsg.Text = ""; }

Werk je met Validation Controls in Template fields van de GridView dan kan je met de IsValid eigenschap van de pagina werken, als de IsValid false is (een validatie mislukt) dan wordt de updateactie geannuleerd.

Deze werkwijze kan ook toegepast worden voor andere databaseacties.

12.7 GridView - records verwijderen

12.7.1.1 Typed DataSet

Het verwijderen van records uit met behulp van een GridView gekoppeld aan een ObjectDataSource met DataSet met automatisch gemaakte Stored Procedures is heel eenvoudig: via smart tag zet je een vinkje bij Enable deleting.

12.7.1.2 Typed DataSet - eigen Stored Procedures

Maak een Stored procedure in nascholing.mdf:

174

Frank Horemans

Page 175: Cursus ASP.net 1

CREATE PROCEDURE dbo.NascholingDelete(

@id int)AS

SET NOCOUNT OFF;DELETE FROM nascholing WHERE id = @id;

De GridView is gebaseerd op de DataSet geconfigureerd in DSNascholing_eigenSTP.xsd, open deze file, rechtsklik de NascholingSelectSortTableAdapter en stel NascholingDelete in als DeleteMethode

Sla DSNascholing_eigenSTP.xsd op Localiseer de ObjectDataSource op de Web Form en kies configure via smart tag

Als Deletemethod moet hier de methode Delete staan zoals automatisch aangemaakt door de TableAdapter, vul desnoods Delete in als naam van de DeleteMethod in de eigenschappen van deze ObjectDataSource

Doordat we de configuratiewizard opnieuw hebben doorlopen moet het argument OldValuesParameterFormatString weer verwijderd of aangepast worden (zoals bij het editeren)

Verifiëer dat in de property DataKeyNames van de GridView id staat aangegeven

12.7.1.3 Eigen ObjectDataSource - 3-tier

De stored procedure NascholingDelete werd reeds aangemaakt

Voorzie een methode in de DAL

NascholingDB.cs

...public static void Delete(int id)

175

Frank Horemans

Page 176: Cursus ASP.net 1

{ SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NascholingConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("NascholingDelete", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.AddWithValue("@id", id);

myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close();}...Voorzie een methode in de Logic-layer: Nascholing.cs[DataObjectMethod(DataObjectMethodType.Delete)]public static void Delete(Nascholing n){ NascholingDB.Delete(n.Id);}

Localiseer de ObjectDataSource van de betreffende GridView Geef als DeleteMethod Delete op en als DeleteParameter id

Je kan dit ook doen via smart tag - configure, het vervelende is dat je dan de UpdateParameters van het vorige cursusonderdeel opnieuw moet opgeven om het updaten niet om zeep te helpen.

GridView: DataKeyNames: id

12.8 GridView - rijen selecteren

We hebben in de voorgaande cursusonderdelen gezien hoe je datamanipulaties kan doen in een GridView met behulp van Commandfields edit, update, cancel en delete. Soms zal je toepassingen maken waarbij een rij uit een GridView geselecteerd moet kunnen worden om bv. deze rij van buiten de GridView te manipuleren.

Voor elk van de reeds gemaakte GridViews is dit heel eenvoudig via smart tag- Enable Editing te verwezenlijken.

Voeg een Label LblRij (lege Text) toe aan de Web Form Maak een eventhandler voor SelectedIndexChanged van de GridView

protected void GridView2_SelectedIndexChanged(object sender, EventArgs e){

176

Frank Horemans

Page 177: Cursus ASP.net 1

LblRij.Text = "Rij: " +GridView2.SelectedRow.RowIndex.ToString();}

12.9 GridView: gegevens uit een rij tonen

De gegevens in de rij van een GridView zullen soms op een andere plaats van de toepassing getoond moeten worden.

Voeg een Label LblGegevens toe aan de Web Form

In het vorige voorbeeld heb je gezien hoe je het geslecteerde rijnummer kan opvragen. De gegevens uit een rij van de GridView kan je zowieso ophalen met volgende code:

protected void GridView2_SelectedIndexChanged(object sender, EventArgs e){ LblRij.Text = "Rij: " +GridView2.SelectedRow.RowIndex.ToString();

string naam = GridView2.SelectedRow.Cells[2].Text; LblGegevens.Text = "Naam nascholing: " + naam;}

Een belangrijk nadeel aan deze werkwijze is het feit dat je het kolomnummer van de gewenste cel moet kennen.

Beter is volgende werkwijze: neem alle velden die je nodig hebt op in de collectie DataKeyNames van de GridView, dit kan je zelfs via een dialoogvenster in Visual Studio doen.

Nu kan je de gegevens van de geselecteerde rij in de GridView benaderen door de SelectedDataKey-collectie op te vragen:

177

Frank Horemans

Page 178: Cursus ASP.net 1

protected void GridView2_SelectedIndexChanged(object sender, EventArgs e){ LblRij.Text = "Rij: " +GridView2.SelectedRow.RowIndex.ToString();

DataKey data = GridView2.SelectedDataKey; LblGegevens.Text = data.Values["Naam"] + " - " + data.Values["Plaats"] + " - " + data.Values["Datum"] + " - " + data.Values["Prijs"] + " - " + data.Values["Actief"];

}

Dit levert volgend resultaat op:

GridView: rijen aanpassen

We zullen er nu voor zorgen dat de cursussen waarvoor Actief op false is ingesteld niet meer aangepast kunnen worden door deze rijen te disablen.

Maak een eventhandler voor de event RowDataBound van de GridView

protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e){ if (e.Row.RowType == DataControlRowType.DataRow) { object dataitem = e.Row.DataItem; e.Row.Enabled = (bool)DataBinder.Eval(dataitem,"Actief"); }}

We controleren eerst of de rij een DataRow is (het kan ook bv. een Header of Footer zijn).

178

Frank Horemans

Page 179: Cursus ASP.net 1

DetailsView - gegevens bekijken

Een component die speciaal werd ontworpen om de detailgegevens van een geselecteerde record te bekijken is de DetailsView.

Deze component ondersteunt ook update, insert en delete-acties

We werken verder met de GridView die gekoppeld is aan een ObjectDataSource die gebruik maakt van ons eigen 3-tier klassenmodel, voor de andere situaties (bvb. typed DataSet) blijven de principes gelijklopend.

Daar in we in ons geval de DetailsView gebruiken voor het weergeven van één nascholing maken we een Stored Procedure om een nascholing op te halen op basis van het id

CREATE PROCEDURE dbo.NascholingSelectById(

@id int)AS

SELECT id, naam, plaats, datum, prijs, actiefFROM nascholingWHERE id = @idRETURN

Maak een methode in de DAL laag:

NascholingDB.cs

...public static DataSet GetNascholingById(int id){ SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NascholingConn"].ConnectionString);

SqlCommand myCommand = new SqlCommand("NascholingSelectById", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.AddWithValue("@id", id);

SqlDataAdapter da = new SqlDataAdapter(myCommand);

DataSet ds = new DataSet("DsNascholing"); da.Fill(ds, "Nascholingen"); return ds;

179

Frank Horemans

Page 180: Cursus ASP.net 1

}...

Voorzie een methode in de Logic-laag:

public static Nascholing GetNascholingById(int id){ Nascholing d = new Nascholing(); try { DataSet ds = NascholingDB.GetNascholingById(id); DataTable dt = ds.Tables["Nascholingen"];

d.Id = Convert.ToInt32(dt.Rows[0]["id"]); d.Naam = dt.Rows[0]["naam"].ToString(); d.Plaats = dt.Rows[0]["plaats"].ToString(); d.Datum = Convert.ToDateTime(dt.Rows[0]["datum"]); d.Prijs = Convert.ToDecimal(dt.Rows[0]["prijs"]); d.Actief = Convert.ToBoolean(dt.Rows[0]["actief"]); } catch { d = null; } return d;}

Voorzie een DetailsView op de Web Form (eventueel mooi schikken t.o.v. de GridView met behulp van een tabel)

Kies een Auto Format voor de DetailsView Kies Choose DataSource - New DataSource Maak een ObjectDataSource ODSNascholingDetail Business object: Logic.nascholingen Select methode: GetNascholingById Parameter voor de Selectmethode instellen: uitlezen uit de GridView!:

180

Frank Horemans

Page 181: Cursus ASP.net 1

Op deze manier 'luistert' deze ObjectDataSource naar veranderingen in de GridView, je hoeft niks meer te programmeren in het event SelectedIndexChanged

Via smart tag - edit fields kan je de velden in de DetailsView nog wat aanpassen (volgorde aanpassen, invisible maken, formaat, ...)

DetailsView - gegevens toevoegen

De Control DetailsView kan ook gebruikt worden om acties uit te voeren op de database: update, insert en delete.

Aangezien we update en delete al hebben besproken voor de GridView beginnen we met de actie insert: toevoegen van records.

181

Frank Horemans

Page 182: Cursus ASP.net 1

Maak een stored procedure in nascholing.mdf

CREATE PROCEDURE dbo.NascholingInsert(

@naam varchar(50),@plaats varchar(50),@datum datetime,@prijs money,@actief bit

)AS

SET NOCOUNT OFF;INSERT INTO nascholing (naam, plaats, datum, prijs, actief) VALUES(@naam,@plaats,@datum,@prijs,@actief)

Voorzie een methode in de DAL

NascholingDB.cs

...public static void Insert(string naam, string plaats, DateTime datum, decimal prijs, bool actief) { SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["NascholingConn"].ConnectionString); SqlCommand myCommand = new SqlCommand("NascholingInsert", myConnection); myCommand.CommandType = CommandType.StoredProcedure; myCommand.Parameters.AddWithValue("@naam", naam); myCommand.Parameters.AddWithValue("@plaats", plaats); myCommand.Parameters.AddWithValue("@datum", datum); myCommand.Parameters.AddWithValue("@prijs", prijs); myCommand.Parameters.AddWithValue("@actief", actief);

myConnection.Open(); myCommand.ExecuteNonQuery(); myConnection.Close(); }...

Voorzie een methode in de Logic-laag

[DataObjectMethod(DataObjectMethodType.Insert)]public static void Insert(Nascholing n){ NascholingDB.Insert(n.Naam, n.Plaats, n.Datum, n.Prijs, n.Actief); ;}

Pas de ObjectDataSource ODSNascholingDetail aan via smart tag - configure: stel de methode Insert in als Insertmethode.

We moeten de InsertParameters typeren (anders hebben we weer vodden met de DateTime-parameter)

182

Frank Horemans

Page 183: Cursus ASP.net 1

<asp:ObjectDataSource ID="ODSNascholingDetail" runat="server" DataObjectTypeName="Logic.Nascholing" InsertMethod="Insert" OldValuesParameterFormatString="original_{0}" SelectMethod="GetNascholingById" TypeName="Logic.Nascholingen"> <SelectParameters> <asp:ControlParameter ControlID="GridView2" Name="id" PropertyName="SelectedValue" Type="Int32" /> </SelectParameters> <InsertParameters> <asp:Parameter Name="naam" Type="String" /> <asp:Parameter Name="plaats" Type="String" /> <asp:Parameter Name="prijs" Type="Decimal" /> <asp:Parameter Name="datum" Type="DateTime" /> <asp:Parameter Name="actief" Type="Boolean" /> </InsertParameters></asp:ObjectDataSource>

Zet de eigenschap AutoGenerateInsertButton van de DetailsView op true (of via smart tag kies je Enable inserting)

DetailsView - gegevens editeren en verwijderen

Om editeren en verwijderen via de DetailsView mogelijk te maken passen we eerst de ObjectDataSource aan.

Configureer de ObjectDataSource zodat NascholingUpdate en NascholingDelete uitgevoerd kunnen worden.

Bij de DataKeyNames van de GridView voeg je id toe. Enable editing en enable deleting van de GridView

Blijkbaar is er nu een probleempje met de Decimal waarde voor de prijs, we moeten daar nu met een '.' werken ipv ','

183

Frank Horemans

Page 184: Cursus ASP.net 1

13 GEAVANCEERDE DATABINDING

1. DataList: dynamische inhoud met ItemDataBound 2. DataList: eigen format functie

13.1 DataList: dynamische inhoud met ItemDataBound

We werken verder met de toepassing uit het hoofdstuk GridView: de nascholingen-database met DAL en Logic-layer.

We zorgen ervoor dat een figuur aangepast wordt wanneer een nascholing actief of niet-actief is.

Maak een nieuwe Web Form: DataList_nascholing.aspx Voorzie een DataList, kies een Auto Format Kies Choose Data Source - New Data Source: ObjectDataSource met

Logic.Nascholingen als Business-object. Getnascholingen is de selectmethode Via smart tag kies je Edit Templates Voeg een Image ImgActief toe met als ImageUrl: images/new.jpg Voeg een eventhandler voor de DataList toe voor het event ItemDataBound

protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e){ if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { Nascholing n = (Nascholing)e.Item.DataItem;

if (!n.Actief) { Image img = (Image)e.Item.FindControl("ImgActief"); img.ImageUrl = "images/cancel.jpg"; } }

}

13.2 DataList - eigen format functie

Voorzie een nieuwe DataList, kies een Auto Format Kies Choose Data Source - New Data Source (of de datasource uit het vorige

voorbeeld) ObjectDataSource met Logic.Nascholingen als Business-object. Getnascholingen is de selectmethode Via smart tag kies je Edit Templates Voeg een Image ImgActief toe met als ImageUrl: images/new.jpg Kies edit DataBindings voor de Image Voor de eigenschap ImageUrl geef je volgende Custom Binding expression:

ToonActiefFiguur((bool)Eval("Actief"))

184

Frank Horemans

Page 185: Cursus ASP.net 1

Voeg een methode ToonActiefFiguur toe aan de code-behind van de Web Form:

protected string ToonActiefFiguur(bool actief){ if (actief) return "images/new.jpg"; return "images/cancel.jpg";}

185

Frank Horemans

Page 186: Cursus ASP.net 1

14 DATABASES

1. Inleiding 2. Connectiestring 3. Gegevens ophalen: SqlDataAdapter en DataSet 4. Gegevens ophalen: SqlCommand en SqlDataReader 5. Select instructie met parameters 6. Gegevens toevoegen: Insert 7. Gegevens bewerken: Update 8. Gegevens verwijderen: Delete 9. Gegevens sorteren 10. Stored Procedures gebruiken

14.1 Inleiding

In dit hoofdstuk leer je hoe je ASP.net kan gebruiken voor toepassingen die verbinding maken met een server-side gegevensbron zoals een SQL Server Database.

De basisklassen die je hiervoor nodig hebt leer je kennen in de cursus ADO.net.

Database Spionshop.mdf voor SQL Server downloaden (unzippen, toevoegen via Alle Taken > Attach Database, eigen uid en pwd gebruiken)

14.2 Connectiestring

Meestal zal je binnen een toepassing meermaals verbinden met dezelfde database op dezelfde SQL-server. Vandaar dat het een goed idee is om de connectiestring op te nemen in het algemene configuratiebestand Web.config:

Web.config

<?xml version="1.0" encoding="utf-8" ?><configuration> <appSettings> <add key="SpionString" value="server=(local);database=Spionshop;uid=spion;pwd=spionpas;" /> </appSettings>

<system.web>...

Je kan de gegevens binnen het configuratiebestand benaderen via de namespace System.Configuration.

14.3 Gegevens ophalen: SqlDataAdapter en DataSet

Je kan nu heel eenvoudig de gegevens uit een database laden in een DataGrid:

186

Frank Horemans

Page 187: Cursus ASP.net 1

Plaats een DataGrid DataGrid1 op een Web Form

...using System.Configuration;...

private void Page_Load(object sender, System.EventArgs e){ SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlDataAdapter da = new SqlDataAdapter("select * from Klant", conn);

DataSet ds = new DataSet(); da.Fill(ds, "Klanten");

DataGrid1.DataSource=ds.Tables["Klanten"].DefaultView; DataGrid1.DataBind();

}

Hier vullen we een SqlConnection-object met de connectiegegevens uit het bestand Web.config.

We laten een SQL-string los op deze connectie en vullen zo een SqlDataAdapter.

Met de methode Fill van de SqlDataAdapter vullen we een DataSet met de resultaatgegevens.

We koppelen de eigenschap DefaultView van de gewenste tabel uit de DataSet aan de eigenschap DataSource van de DataGrid (DefaultView representeert de huidige status van de tabel, ook eventuele wijzigingen die reeds runtime zijn gedaan)

We binden de tabel "Klanten" uit de DataSet aan de DataGrid.

Voorzie een leuke opmaak: HeaderStyle, ItemStyle, AlternatingItemStyle (VS.net)

Een alternatief is het opgeven van de eigenschap DataMember naast de eigenschap DataSource. Nu gebruikt ASP.net automatisch de DefaultView van de tabel:

DataGrid1.DataSource=ds;DataGrid1.DataMember = "Klanten";DataGrid1.DataBind();

187

Frank Horemans

Page 188: Cursus ASP.net 1

14.4 Gegevens ophalen: SqlCommand en SqlDataReader

Voor een forward-only, read-only bewerking kan je een SqlDataReader binden aan een DataGrid:

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);SqlCommand cmd = new SqlCommand("select * from Klant", conn);conn.Open();SqlDataReader dr = cmd.ExecuteReader();DataGrid1.DataSource = dr;DataGrid1.DataBind();conn.Close();

14.5 Select instructie met parameters

In de cursus ADO.net leerde je reeds hoe je parameters kan toevoegen aan een SqlCommand. Deze keer leer je hoe je een parameter kan toevoegen aan een SqlDataAdapter om een DataSet te vullen.

In deze toepassing vullen we een ListBox met de categorieën uit de database. Wanneer de gebruiker een categorie kiest worden de artikels uit deze categorie getoond in een DataGrid. Voor het vullen van de DataGrid kijken we naar de SelectedValue van de DataList die het cat_id voor deze categorie bevat.

We voegen de SqlParameter toe aan het SelectCommand van de SqlDataAdapter.

Je kan voor de DataGrid de eigenschap EnableViewState best op false plaatsen. Het heeft geen zin de inhoud van de DataGrid te laten opnemen in de ViewState wanneer deze bij elke PostBack wijzigt.

...using System.Data.SqlClient;using System.Configuration;

namespace Basis{ public class Parameter : System.Web.UI.Page { protected System.Web.UI.WebControls.DataGrid dgArtikel; protected System.Web.UI.WebControls.ListBox lstCategorie; private void Page_Load(object sender, System.EventArgs e)

188

Frank Horemans

Page 189: Cursus ASP.net 1

{ if(!IsPostBack) { SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlCommand cmd = new SqlCommand("select * from Categorie order by categorie", conn); conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); lstCategorie.DataSource = dr; lstCategorie.DataTextField = "Categorie"; lstCategorie.DataValueField = "cat_id"; lstCategorie.DataBind(); conn.Close(); if(lstCategorie.Items.Count > 0) { lstCategorie.SelectedIndex = 0; VulArtikels(); } } }

private void VulArtikels() { String sql = @"select artikel, omschrijving, verkoopprijs from artikel where cat_id = @catid order by artikel";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlDataAdapter da = new SqlDataAdapter(sql, conn);

da.SelectCommand.Parameters.Add(new SqlParameter("@catid",SqlDbType.SmallInt)); da.SelectCommand.Parameters["@catid"].Value = lstCategorie.SelectedValue;

DataSet ds = new DataSet(); da.Fill(ds, "Artikels");

dgArtikel.DataSource= ds; dgArtikel.DataMember = "Artikels"; dgArtikel.DataBind(); }

...

private void lstCategorie_SelectedIndexChanged(object sender, System.EventArgs e) { VulArtikels(); } }}

189

Frank Horemans

Page 190: Cursus ASP.net 1

14.6 Gegevens toevoegen: Insert

We staan de gebruiker toe artikels toe te voegen aan de database.

Hiertoe voorzien we TextBox-controls voorzien van Input Validation Conrols waar de gebruiker de gegevens voor een nieuw artikel kan ingeven. We voorzien een Button waarmee de gebruiker de opdracht kan uitvoeren.

Wanneer de pagina valid is worden de gegevens van het artikel toegevoegd, rekening houdend met de geselecteerde categorie.

...using System.Data.SqlClient;using System.Configuration;

namespace Basis{ public class Toevoegen : System.Web.UI.Page { protected System.Web.UI.WebControls.DataGrid dgArtikel; protected System.Web.UI.WebControls.TextBox txtArtikel; protected System.Web.UI.WebControls.TextBox txtOmschrijving; protected System.Web.UI.WebControls.TextBox txtPrijs; protected System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1; protected System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator2; protected System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator3; protected System.Web.UI.WebControls.Button cmdToevoegen; protected System.Web.UI.WebControls.CompareValidator CompareValidator1; protected System.Web.UI.WebControls.Label lblBericht; protected System.Web.UI.WebControls.ListBox lstCategorie; private void Page_Load(object sender, System.EventArgs e)

190

Frank Horemans

Page 191: Cursus ASP.net 1

{ if(!IsPostBack) { SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlCommand cmd = new SqlCommand("select * from Categorie order by categorie", conn); conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); lstCategorie.DataSource = dr; lstCategorie.DataTextField = "Categorie"; lstCategorie.DataValueField = "cat_id"; lstCategorie.DataBind(); conn.Close(); if(lstCategorie.Items.Count > 0) { lstCategorie.SelectedIndex = 0; VulArtikels(); } } }

private void VulArtikels() { String sql = @"select artikel, omschrijving, verkoopprijs from artikel where cat_id = @catid order by artikel";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlDataAdapter da = new SqlDataAdapter(sql, conn);

da.SelectCommand.Parameters.Add(new SqlParameter("@catid",SqlDbType.SmallInt)); da.SelectCommand.Parameters["@catid"].Value = lstCategorie.SelectedValue;

DataSet ds = new DataSet(); da.Fill(ds, "Artikels");

dgArtikel.DataSource= ds; dgArtikel.DataMember = "Artikels"; dgArtikel.DataBind(); }

...

private void lstCategorie_SelectedIndexChanged(object sender, System.EventArgs e) { VulArtikels(); }

private void cmdToevoegen_Click(object sender, System.EventArgs e) { lblBericht.Text = "";

191

Frank Horemans

Page 192: Cursus ASP.net 1

if (Page.IsValid) { SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);

String sql = @"insert into artikel (artikel, omschrijving, verkoopprijs, cat_id) values (@artikel, @omschrijving, @verkoopprijs, @cat_id)";

SqlCommand cmd = new SqlCommand(sql, conn);

cmd.Parameters.Add(new SqlParameter("@artikel", SqlDbType.VarChar,50)); cmd.Parameters["@artikel"].Value = txtArtikel.Text;

cmd.Parameters.Add(new SqlParameter("@omschrijving", SqlDbType.VarChar, 500)); cmd.Parameters["@omschrijving"].Value = txtOmschrijving.Text;

cmd.Parameters.Add(new SqlParameter("@verkoopprijs", SqlDbType.SmallMoney, 4)); cmd.Parameters["@verkoopprijs"].Value = txtPrijs.Text;

cmd.Parameters.Add(new SqlParameter("@cat_id", SqlDbType.SmallInt, 2)); cmd.Parameters["@cat_id"].Value = lstCategorie.SelectedValue;

cmd.Connection.Open();

try { cmd.ExecuteNonQuery(); lblBericht.Text = "<b>Record toegevoegd</b>"; lblBericht.Style["color"] = "green"; } catch (SqlException ex) { lblBericht.Text = "Fout: record kon niet worden toegevoegd:<br> " +ex.Message; lblBericht.Style["color"] = "red"; }

cmd.Connection.Close(); }

VulArtikels();

} }}

192

Frank Horemans

Page 193: Cursus ASP.net 1

14.7 Gegevens bewerken: Update

Met een DataGrid kan je op een eenvoudige manier functionaliteit om gegevens te bewerken invoegen.

De DataGrid kan een EditCommandColumn bevatten die links weergeeft die drie speciale events uitvoeren: EditCommand, UpdateCommand, en CancelCommand. Deze kolom kan je in Visual Studio.net eenvoudig toevoegen via de Property Builder... > Columns > Button Column > Edit, Update, Cancel Je kan de tekst voor de hyperlinks zelf instellen.

Voor deze toepassing plaats je de eigenschap EnableViewState van de DataGrid weer op true.

Voeg voor de drie besproken events event-handler methoden toe. De UpdateCommand voert de eigenlijke update naar de database uit.

Het is nu wenselijk dat we beschikken over het juiste artikel_id. We zorgen er dus voor dat dit veld ook uit de tabel wordt geladen. Je kan dit veld instellen als DataKeyField van de DataGrid.

dgArtikel.DataKeyField = "artikel_id";

Wens je nu ook meer controle over het weergeven van de kolommen, werk dan bijvoorbeeld met BoundColumns in plaats van automatisch gegenereerde kolommen.

In deze toepassing zorgen we ervoor dat de kolom die de artikel_id's bevat onzichtbaar is.

Zet via de Property Builder het vinkje af bij Create columns dynamically at run-time

Voorzie drie BoundColumns:

o HeaderText: Artikel - DataField: artikel o HeaderText: Omschrijving - DataField: omschrijving o HeaderText: Verkoopprijs - DataField: verkoopprijs

Zorg voor gepaste event-handler code:

Bewerken.aspx.cs

193

Frank Horemans

Page 194: Cursus ASP.net 1

...using System.Data.SqlClient;using System.Configuration;

namespace Basis{

public class Bewerken : System.Web.UI.Page { ... private void Page_Load(object sender, System.EventArgs e) { if(!IsPostBack) { SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlCommand cmd = new SqlCommand("select * from Categorie order by categorie", conn); conn.Open(); SqlDataReader dr = cmd.ExecuteReader(); lstCategorie.DataSource = dr; lstCategorie.DataTextField = "Categorie"; lstCategorie.DataValueField = "cat_id"; lstCategorie.DataBind(); conn.Close(); if(lstCategorie.Items.Count > 0) { lstCategorie.SelectedIndex = 0; VulArtikels(); } } }

private void VulArtikels() { String sql = @"select artikel_id, artikel, omschrijving, verkoopprijs from artikel where cat_id = @catid order by artikel";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlDataAdapter da = new SqlDataAdapter(sql, conn);

da.SelectCommand.Parameters.Add(new SqlParameter("@catid",SqlDbType.SmallInt)); da.SelectCommand.Parameters["@catid"].Value = lstCategorie.SelectedValue;

DataSet ds = new DataSet(); da.Fill(ds, "Artikels");

dgArtikel.DataSource= ds; dgArtikel.DataKeyField = "artikel_id"; dgArtikel.DataMember = "Artikels"; dgArtikel.DataBind();

194

Frank Horemans

Page 195: Cursus ASP.net 1

}

...

private void lstCategorie_SelectedIndexChanged(object sender, System.EventArgs e) { VulArtikels(); }

private void dgArtikel_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) { dgArtikel.EditItemIndex = e.Item.ItemIndex; VulArtikels(); }

private void dgArtikel_CancelCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) { dgArtikel.EditItemIndex = -1; VulArtikels();

}

private void dgArtikel_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) {

lblUpdateBericht.Text="";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); String sql = @"UPDATE artikel SET artikel = @artikel, omschrijving = @omschrijving, verkoopprijs = @verkoopprijs WHERE artikel_id = @artikel_id";

SqlCommand cmd = new SqlCommand(sql, conn);

cmd.Parameters.Add(new SqlParameter("@artikel", SqlDbType.VarChar,50)); cmd.Parameters.Add(new SqlParameter("@omschrijving", SqlDbType.VarChar, 500)); cmd.Parameters.Add(new SqlParameter("@verkoopprijs", SqlDbType.SmallMoney, 4)); cmd.Parameters.Add(new SqlParameter("@artikel_id", SqlDbType.SmallInt, 2));

cmd.Parameters["@artikel_id"].Value = dgArtikel.DataKeys[(int)e.Item.ItemIndex];

// Een array voor alle celwaarden// we lezen dan een voor een met een lus de waarden

van de tekstvakken uit String[] cols = {"@artikel_id","@artikel","@omschrijving","@verkoopprijs"}; lblUpdateBericht.Text = "";

195

Frank Horemans

Page 196: Cursus ASP.net 1

int numCols = e.Item.Cells.Count; for (int i=1; i<numCols; i++) //eerste kolom overslaan, artikel_id werd reeds uitgelezen { String colvalue =((TextBox)e.Item.Cells[i].Controls[0]).Text; if (colvalue == "") { lblUpdateBericht.Text += "Fout: Null-waarde niet toegestaan voor " + cols[i] + "<br>"; }

cmd.Parameters[cols[i]].Value = colvalue; }

if ( lblUpdateBericht.Text != "" ) { lblUpdateBericht.Style["color"] = "red"; return; } cmd.Connection.Open();

try { cmd.ExecuteNonQuery(); lblUpdateBericht.Text = "<b>Record Bewerkt</b>"; lblUpdateBericht.Style["color"] = "green"; dgArtikel.EditItemIndex = -1; } catch (SqlException ex) { lblUpdateBericht.Text = "Fout: update niet geslaagd: " +ex.Message; lblUpdateBericht.Style["color"] = "red"; }

cmd.Connection.Close();

VulArtikels();

} }}

Bewerken.aspx

<%@ Page language="c#" Codebehind="Bewerken.aspx.cs" AutoEventWireup="false" Inherits="Basis.Bewerken" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ><HTML> <HEAD> <title>Parameter</title> <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1"> <meta name="CODE_LANGUAGE" Content="C#">

196

Frank Horemans

Page 197: Cursus ASP.net 1

<meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body> <form id="Form1" method="post" runat="server"> <P> <TABLE id="Table1" style="BORDER-RIGHT:black 1px solid; BORDER-TOP:black 1px solid; BORDER-LEFT:black 1px solid; BORDER-BOTTOM:black 1px solid" cellSpacing="0" cellPadding="5" border="0"> <TR> <TD style="WIDTH: 126px" vAlign="top"> <P><U><STRONG>Categorie:</STRONG></U></P> <P> <asp:ListBox id="lstCategorie" runat="server" Rows="3" AutoPostBack="True" BackColor="#FFC0C0" ForeColor="#C00000"></asp:ListBox></P> </TD> <TD> <P> </P> <BR> <BR> </TD> </TR> </TABLE> </P> <P> <asp:DataGrid id="dgArtikel" runat="server" BorderColor="#400000" AutoGenerateColumns="False"> <AlternatingItemStyle BackColor="#E0E0E0"></AlternatingItemStyle> <ItemStyle BackColor="Silver"></ItemStyle> <HeaderStyle Font-Size="Medium" ForeColor="Maroon" BackColor="#8080FF"></HeaderStyle> <Columns> <asp:EditCommandColumn ButtonType="LinkButton" UpdateText="OK" CancelText="Annuleren" EditText="Bewerken"></asp:EditCommandColumn> <asp:BoundColumn DataField="artikel" HeaderText="Artikel"></asp:BoundColumn> <asp:BoundColumn DataField="omschrijving" HeaderText="Omschrijving"></asp:BoundColumn> <asp:BoundColumn DataField="verkoopprijs" HeaderText="Verkoopprijs"></asp:BoundColumn> </Columns> </asp:DataGrid></P> <P> <asp:Label id="lblUpdateBericht" runat="server"></asp:Label></P> </form> </body></HTML>

197

Frank Horemans

Page 198: Cursus ASP.net 1

14.7.1.1 TemplateColumn

Soms is het wenselijk om de te editeren inhoud weer te geven in een andere Control dan een standaard TextBox. Hiervoor kan je gebruik maken van een TemplateColumn en de opmaak van de EditItemTemplate.

Via Property Builder > Columns selecteer je de BoundColumn omschrijving Klik op Convert this Column into a template column Rechtsklik de DataGrid > Edit Template > Columns[2] - Omschrijving In de EditItemTemplate geef je voor de TextBox als TextMode MultiLine op

We kunnen nu niet meer op dezelfde manier als hierboven de TextBox aanspreken, deze keer gebruiken we de methode FindControl.

cmd.Parameters["@omschrijving"].Value = ((TextBox)e.Item.FindControl("txtEditOmschrijving")).Text;

In de oplossingencode gebruiken we bijgevolg geen lus meer om de bewerkte waarden op te vragen.

Bewerken2.aspx.cs

...private void dgArtikel_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) { lblUpdateBericht.Text="";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); String sql = @"UPDATE artikel SET artikel = @artikel, omschrijving = @omschrijving, verkoopprijs = @verkoopprijs WHERE artikel_id = @artikel_id";

SqlCommand cmd = new SqlCommand(sql, conn);

198

Frank Horemans

Page 199: Cursus ASP.net 1

cmd.Parameters.Add(new SqlParameter("@artikel", SqlDbType.VarChar,50)); cmd.Parameters.Add(new SqlParameter("@omschrijving", SqlDbType.VarChar, 500)); cmd.Parameters.Add(new SqlParameter("@verkoopprijs", SqlDbType.SmallMoney, 4)); cmd.Parameters.Add(new SqlParameter("@artikel_id", SqlDbType.SmallInt, 2));

cmd.Parameters["@artikel"].Value =

ControleerVak(((TextBox)e.Item.Cells[1].Controls[0]).Text); cmd.Parameters["@omschrijving"].Value = ControleerVak(((TextBox)e.Item.FindControl("txtEditOmschrijving")).Text); cmd.Parameters["@artikel_id"].Value =

dgArtikel.DataKeys[(int)e.Item.ItemIndex]; cmd.Parameters["@verkoopprijs"].Value =

ControleerVak(((TextBox)e.Item.Cells[3].Controls[0]).Text);

if ( lblUpdateBericht.Text != "" ) { lblUpdateBericht.Style["color"] = "red"; return; } cmd.Connection.Open();

try { cmd.ExecuteNonQuery(); lblUpdateBericht.Text = "<b>Record Bewerkt</b>"; lblUpdateBericht.Style["color"] = "green"; dgArtikel.EditItemIndex = -1; } catch (SqlException ex) { lblUpdateBericht.Text = "Fout: update niet geslaagd: " +ex.Message; lblUpdateBericht.Style["color"] = "red"; }

cmd.Connection.Close();

VulArtikels();

}

private string ControleerVak(string tekst) { if(tekst=="")

199

Frank Horemans

Page 200: Cursus ASP.net 1

{ lblUpdateBericht.Text = "Fout: Null-waarde niet toegestaan"; } return tekst;

}

Bewerken.aspx

<%@ Page language="c#" Codebehind="Bewerken2.aspx.cs" AutoEventWireup="false" Inherits="Basis.Bewerken2" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ><HTML> <HEAD> <title>Parameter</title> <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1"> <meta name="CODE_LANGUAGE" Content="C#"> <meta name="vs_defaultClientScript" content="JavaScript"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> </HEAD> <body> <form id="Form1" method="post" runat="server"> <P> <TABLE id="Table1" style="BORDER-RIGHT:black 1px solid; BORDER-TOP:black 1px solid; BORDER-LEFT:black 1px solid; BORDER-BOTTOM:black 1px solid" cellSpacing="0" cellPadding="5" border="0"> <TR> <TD style="WIDTH: 126px" vAlign="top"> <P><U><STRONG>Categorie:</STRONG></U></P> <P> <asp:ListBox id="lstCategorie" runat="server" Rows="3" AutoPostBack="True" BackColor="#FFC0C0" ForeColor="#C00000"></asp:ListBox></P> </TD> <TD> <P> </P> <BR> <BR> </TD> </TR> </TABLE> </P> <P> <asp:DataGrid id="dgArtikel" runat="server" BorderColor="#400000" AutoGenerateColumns="False"> <AlternatingItemStyle BackColor="#E0E0E0"></AlternatingItemStyle> <ItemStyle BackColor="Silver"></ItemStyle> <HeaderStyle Font-Size="Medium" ForeColor="Maroon" BackColor="#8080FF"></HeaderStyle> <Columns> <asp:EditCommandColumn ButtonType="LinkButton" UpdateText="OK" CancelText="Annuleren" EditText="Bewerken"></asp:EditCommandColumn>

200

Frank Horemans

Page 201: Cursus ASP.net 1

<asp:BoundColumn DataField="artikel" HeaderText="Artikel"></asp:BoundColumn> <asp:TemplateColumn HeaderText="Omschrijving"> <ItemTemplate> <asp:Label id=Label1 runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.omschrijving") %>'> </asp:Label> </ItemTemplate> <EditItemTemplate> <asp:TextBox id=txtEditOmschrijving runat="server" Width="300px" TextMode="MultiLine" Text='<%# DataBinder.Eval(Container, "DataItem.omschrijving") %>'> </asp:TextBox> </EditItemTemplate> </asp:TemplateColumn> <asp:BoundColumn DataField="verkoopprijs" HeaderText="Verkoopprijs"></asp:BoundColumn> </Columns> </asp:DataGrid></P> <P> <asp:Label id="lblUpdateBericht" runat="server"></asp:Label></P> </form> </body></HTML>

Met een TemplateColumn kan je zelfs Input Validation Controls aan de EditItemTemplate toevoegen !

14.8 Gegevens verwijderen: Delete

Je kan op een eenvoudige manier een kolom aan een DataGrid toevoegen waarmee je gegevens kan verwijderen. Dit doe je door een ButtonColumn toevoegen met CommandName Delete. Dit kan je voor jou laten doen door Visual Studio.net:

Rechtsklik de DataGrid, Kies Property Builder... Kies het onderdeel Columns Kies bij de Button Column voor een type Delete, voeg de kolom toe Laat de CommandName op Delete staan

201

Frank Horemans

Page 202: Cursus ASP.net 1

Via de eigenschappen van de DataGrid voeg je een event-handler methode toe voor de event DeleteCommand:

private void dgArtikel_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e) { SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);

String sql = "DELETE from Artikel where artikel_id = @artikel_id";

SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.Add(new SqlParameter("@artikel_id", SqlDbType.SmallInt, 2)); cmd.Parameters["@artikel_id"].Value = dgArtikel.DataKeys[(int)e.Item.ItemIndex];

cmd.Connection.Open();

try { cmd.ExecuteNonQuery(); lblUpdateBericht.Text = "<b>Record Verwijderd</b>"; lblUpdateBericht.Style["color"] = "green"; } catch (SqlException ex) { lblUpdateBericht.Text = "Fout: record niet verwijderd " +ex.Message; lblUpdateBericht.Style["color"] = "red"; }

cmd.Connection.Close();

VulArtikels();

}

202

Frank Horemans

Page 203: Cursus ASP.net 1

14.9 Gegevens sorteren

Wanneer voor een DataGrid de eigenschap AllowSorting op true staat ingesteld, worden de kolomkoppen als LinkButtons weergegeven. Wanneer je een LinkButton aanklikt wordt het event SortCommand van de DataGrid uitgevoerd. Standaard wordt de naam van de kolom meegegeven als waarde voor de eigenschap SortExpression van het argument DataGridSortCommandEventArgs in de event-handler. Deze SortExpression kan je gebruiken om de eigenschap Sort van de onderliggende DataView in te stellen.

Wanneer je de kolommen automatisch laat genereren wordt de SortExpression voor elke kolom automatisch ingesteld, gebruik je zelfgeplaatste kolommen zoals BoundColumn, dan stel je de SortExpression voor de kolom zelf in (op de naam van een veld van de onderliggende tabel).

Doordat we in onze toepassing PostBacks naar de server hebben wanneer de gebruiker een andere categorie kiest laat ik de gekozen SortExpression bijhouden in de ViewState.

Via Property Builder > General > plaats je een vinkje bij Allow Sorting Geef voor de BoundColumns de naam van het te sorteren veld in als

SortExpression, deze is hetzelfde als de waarde voor DataField Via de eigenschappen van de DataGrid voeg je een event-handler toe voor de

event SortCommand. Pas je code aan zodanig dat de DataGrid gevuld wordt met een gesorteerde

DataView.

Sorteren.aspx.cs

private void VulArtikels() { String sql = @"select artikel_id, artikel, omschrijving, verkoopprijs from artikel where cat_id = @catid order by artikel";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);

203

Frank Horemans

Page 204: Cursus ASP.net 1

SqlDataAdapter da = new SqlDataAdapter(sql, conn);

da.SelectCommand.Parameters.Add(new SqlParameter("@catid",SqlDbType.SmallInt)); da.SelectCommand.Parameters["@catid"].Value = lstCategorie.SelectedValue;

DataSet ds = new DataSet(); da.Fill(ds, "Artikels");

DataView bron =ds.Tables["Artikels"].DefaultView; if(ViewState["SortArtikels"] == null) ViewState["SortArtikels"] = "artikel"; bron.Sort = ViewState["SortArtikels"].ToString();

dgArtikel.DataSource= bron; dgArtikel.DataKeyField = "artikel_id"; dgArtikel.DataBind(); }

...

private void dgArtikel_SortCommand(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e) { ViewState["SortArtikels"] = e.SortExpression; VulArtikels();

}

Sorteren.aspx

<%@ Page language="c#" Codebehind="Sorteren.aspx.cs" AutoEventWireup="false" Inherits="Basis.Sorteren" %>... <asp:DataGrid id="dgArtikel" runat="server" BorderColor="#400000" AutoGenerateColumns="False" AllowSorting="True"> <AlternatingItemStyle BackColor="#E0E0E0"></AlternatingItemStyle> <ItemStyle BackColor="Silver"></ItemStyle> <HeaderStyle Font-Size="Medium" ForeColor="Maroon" BackColor="#8080FF"></HeaderStyle> <Columns> <asp:BoundColumn DataField="artikel" SortExpression="artikel" HeaderText="Artikel"></asp:BoundColumn> <asp:TemplateColumn SortExpression="omschrijving" HeaderText="Omschrijving"> <ItemTemplate> <asp:Label id=Label1 runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.omschrijving") %>'> </asp:Label> </ItemTemplate> <EditItemTemplate> <asp:TextBox id=txtEditOmschrijving runat="server" Width="300px" TextMode="MultiLine" Text='<%# DataBinder.Eval(Container, "DataItem.omschrijving") %>'> </asp:TextBox> </EditItemTemplate>

204

Frank Horemans

Page 205: Cursus ASP.net 1

</asp:TemplateColumn> <asp:BoundColumn DataField="verkoopprijs" SortExpression="verkoopprijs" HeaderText="Verkoopprijs"></asp:BoundColumn> </Columns> </asp:DataGrid></P> <P> <asp:Label id="lblUpdateBericht" runat="server"></asp:Label></P> </form> </body></HTML>

14.9.1.1 Oplopend en aflopend

De sortering van gegevens gebeurt standaard oplopend (ascending). Door aan de methode Sort van de DataView een extra string " DESC" mee te geven kan je de gegevens ook aflopend (descending) sorteren.

In de toepassing zorgen voor een extra element in de ViewState: SortArtikelsOplopend. We houden bij of er oplopend of aflopend wordt gesorteerd. We wisselen de sorteerorde wanneer twee keer op eenzelfde kolomkop wordt geklikt.

...

private void VulArtikels() { String sql = @"select artikel_id, artikel, omschrijving, verkoopprijs from artikel where cat_id = @catid order by artikel";

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]); SqlDataAdapter da = new SqlDataAdapter(sql, conn);

da.SelectCommand.Parameters.Add(new SqlParameter("@catid",SqlDbType.SmallInt));

205

Frank Horemans

Page 206: Cursus ASP.net 1

da.SelectCommand.Parameters["@catid"].Value = lstCategorie.SelectedValue;

DataSet ds = new DataSet(); da.Fill(ds, "Artikels");

DataView bron =ds.Tables["Artikels"].DefaultView; if(ViewState["SortArtikelsOplopend"] == null) ViewState["SortArtikelsOplopend"] = true; if(ViewState["SortArtikels"] == null) ViewState["SortArtikels"] = "artikel"; if((bool)ViewState["SortArtikelsOplopend"]) bron.Sort = ViewState["SortArtikels"].ToString(); else bron.Sort = ViewState["SortArtikels"].ToString() +" DESC";

dgArtikel.DataSource= bron; dgArtikel.DataKeyField = "artikel_id"; dgArtikel.DataBind(); }

...

private void lstCategorie_SelectedIndexChanged(object sender, System.EventArgs e) { VulArtikels(); }

private void dgArtikel_SortCommand(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e) { if(ViewState["SortArtikels"].Equals(e.SortExpression)) ViewState["SortArtikelsOplopend"] = !(bool)ViewState["SortArtikelsOplopend"]; ViewState["SortArtikels"] = e.SortExpression; VulArtikels();

}

}}

14.10 Stored Procedures gebruiken

Om de performatie van je toepassing te verhogen kan je gebruik maken van Stored Procedures. De code van je applicatie wordt ook toegankelijker, daar je nu geen SQL-statements meer hoeft op te nemen in je toepassing. Wanneer de database wijzigt hoef je de applicatie niet aan te passen, maar voer je de wijzigingen op Database-niveau door.

206

Frank Horemans

Page 207: Cursus ASP.net 1

14.10.1.1 Stored Procedures maken

In SQL-Server kan je Stored Procedures maken via de SQL Query Analyzer.

CREATE PROCEDURE spToonArtikelGegevensASSELECT artikel, omschrijvingFROM artikelORDER BY artikel

14.10.1.2 Stored Procedures gebruiken

Werk je rechtstreeks met een SqlCommand, bijvoorbeeld voor het vullen van een SqlDataReader, dan stel je het CommandType van de SqlCommand in op StoredProcedure, en de CommandText op de naam van de Stored Procedure.

Voorzie een DataGrid DataGrid1 op een Web Form De Page_Load methode bevat volgende code:

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);

//STP aanroepen voor een DataReaderSqlCommand cmd = new SqlCommand("spToonArtikelGegevens",conn);cmd.CommandType = CommandType.StoredProcedure;

conn.Open();SqlDataReader dr = cmd.ExecuteReader();DataGrid1.DataSource=dr;DataGrid1.DataBind();conn.Close();

207

Frank Horemans

Page 208: Cursus ASP.net 1

Je kan ook een DataSet vullen met behulp van een Stored Procedure.

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);

//STP aanroepen voor een DataAdapterSqlDataAdapter da = new SqlDataAdapter("drie duurste producten", conn);da.SelectCommand.CommandType = CommandType.StoredProcedure;

DataSet ds = new DataSet();da.Fill(ds, "ArtikelGegevens");

DataGrid2.DataSource=ds;DataGrid2.DataMember = "ArtikelGegevens";DataGrid2.DataBind();

De Stored Procedure drie duurste producten ziet er als volgt uit:

CREATE procedure "Drie duurste producten" ASSET ROWCOUNT 3SELECT artikel, verkoopprijsFROM artikelORDER BY verkoopprijs DESC

14.10.1.3 Parameters aan Stored Procedures doorgeven

Je kan analoog aan het werken met gewone SQL-statements ook parameters doorgeven aan een Stored Procedure. In het voorbeeld werken we met een SqlDataAdapter en een DataSet, je kan natuurlijk ook parameters meegeven met een SqlCommand voor het vullen van een SqlDataReader.

De Stored Procedure:

208

Frank Horemans

Page 209: Cursus ASP.net 1

CREATE PROCEDURE ArtikelUitCategorie @CatID smallintASSELECT artikel, omschrijving, verkoopprijsFROM artikelWHERE cat_id = @CatIDORDER BY artikel

Code in Page_Load:

SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["SpionString"]);

//STP met parameter aanroepen voor een DataAdapterSqlDataAdapter daAC = new SqlDataAdapter("ArtikelUitCategorie", conn);daAC.SelectCommand.CommandType = CommandType.StoredProcedure;

daAC.SelectCommand.Parameters.Add(new SqlParameter("@CatID", SqlDbType.SmallInt, 15));daAC.SelectCommand.Parameters["@CatID"].Value = 1;

DataSet dsAC = new DataSet();daAC.Fill(dsAC, "ArtikelGegevens");

DataGrid3.DataSource=dsAC;DataGrid3.DataMember = "ArtikelGegevens";DataGrid3.DataBind();

209

Frank Horemans

Page 210: Cursus ASP.net 1

15 BUSINESS OBJECTEN

1. Inleiding 2. 2-Tier 3. 3-Tier 4. Oefening: online shop

15.1 Inleiding

In dit hoofdstuk leer je hoe je verschillende onderdelen van een applicatie kan scheiden. Veelal wordt gesproken over lagen of layers van een applicatie. Deze termen geven aan hoe de verschillende aspecten fysiek van elkaar worden gescheiden. Voor een ASP.net applicatie kunnen we op die manier steeds een client, een server en dikwijls een database-layer onderscheiden.

Met het begrip tier wordt wordt ook een laag aangegeven, maar wordt meestal niet als een fysieke scheidingslijn aangenomen, maar een programmatorische afsplitsing in klassen en groepen van gerateerde klassen. Het is de bedoeling dat de verschillende tiers enkel communiceren met elkaar, maar in principe niks over elkaar hoeven te weten.

Op deze manier kan je je toepassing opbouwen op een gestructureerde manier en kan je later aanpassingen doen in een van de tiers van de applicatie zonder daarvoor andere tiers te moeten manipuleren.

Je kan een toepassing opsplitsen in 2, 3 of meer lagen, algemeen spreken we over een N-Tier structuur.

Een gangbare manier om jouw toepassingen in tiers op te delen is de 3-Tier architectuur:

Prestentatie-laag Business-laag / logische laag Data-laag

15.2 2-Tier applicatie

In deze toepassing maken we gebruik van twee lagen: een presentatielaag en een datalaag. We koppelen de interactie met de database los van de presentatie van de gegevens.

210

Frank Horemans

Page 211: Cursus ASP.net 1

De gebruikte Stored Procedures:

CREATE PROCEDURE CategorieenASSELECT cat_id, categorieFROM categorieORDER BY categorie

CREATE PROCEDURE ArtikelUitCategorie @CatID smallintASSELECT artikel, omschrijving, verkoopprijsFROM artikelWHERE cat_id = @CatIDORDER BY artikel

Maak een klasse DataObj, deze klasse zal interageren met de database. De klasse ontvangt een connectiestring

We hebben twee methoden GetCategorieen en GetArtikelsVoorCategorie. Deze methodes halen de juiste informatie uit de database en retourneren een DataView van de gewenste tabel uit de DataSet.

DataObj.csusing System;using System.Data;using System.Data.SqlClient;

namespace lagen{ /// <summary> /// Klasse voor datatoegang /// </summary> public class DataObj { private String _connStr;

public DataObj() { _connStr = null; }

public DataObj(String connStr) { _connStr = connStr; }

public String ConnectionString { get { return _connStr; } set { _connStr = value; } }

211

Frank Horemans

Page 212: Cursus ASP.net 1

public DataView GetCategorieen() { SqlConnection conn = new SqlConnection(_connStr); SqlDataAdapter da = new SqlDataAdapter("Categorieen", conn); da.SelectCommand.CommandType = CommandType.StoredProcedure;

DataSet ds = new DataSet(); da.Fill(ds, "Categorieen");

return ds.Tables["Categorieen"].DefaultView; }

public DataView GetArtikelsVoorCategorie(short catid) { SqlConnection conn = new SqlConnection(_connStr); SqlDataAdapter da = new SqlDataAdapter("ArtikelUitCategorie", conn);

da.SelectCommand.CommandType = CommandType.StoredProcedure;

da.SelectCommand.Parameters.Add(new SqlParameter("@CatID", SqlDbType.SmallInt, 15)); da.SelectCommand.Parameters["@CatID"].Value = catid;

DataSet ds = new DataSet(); da.Fill(ds, "Artikel");

return ds.Tables["Artikel"].DefaultView; } }}

We maken nu een Web Form met een ListBox lstCategorie en een DataGrid dgArtikel

TweeTier.aspx.cs

using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using System.Configuration;

namespace lagen{ /// <summary> /// Summary description for tweeTier. /// </summary> public class tweeTier : System.Web.UI.Page { protected System.Web.UI.WebControls.ListBox lstCategorie; protected System.Web.UI.WebControls.DataGrid dgArtikel;

212

Frank Horemans

Page 213: Cursus ASP.net 1

private void Page_Load(object sender, System.EventArgs e) { if (!IsPostBack) { DataObj data = new DataObj(ConfigurationSettings.AppSettings["SpionString"]); lstCategorie.DataSource = data.GetCategorieen(); lstCategorie.DataValueField = "cat_id";

lstCategorie.DataTextField = "categorie"; lstCategorie.DataBind(); if(lstCategorie.Items.Count > 0) { lstCategorie.SelectedIndex = 0; VulArtikels();

}

} }

...

private void lstCategorie_SelectedIndexChanged(object sender, System.EventArgs e) { VulArtikels(); } private void VulArtikels() { DataObj data = new DataObj(ConfigurationSettings.AppSettings["SpionString"]); dgArtikel.DataSource = data.GetArtikelsVoorCategorie(Int16.Parse(lstCategorie.SelectedValue)); dgArtikel.DataBind(); } }}

15.2.1.1 Prestentatielaag loskoppelen van Datalaag

In de vorige toepassing werden de lagen eigenlijk niet volledig losgekoppeld. Voor het vullen van de ListBox moeten we de namen van de velden uit de database kennen waarmee we DataValueField en DataTextField van de ListBox willen vullen.

Een eerste manier om dit te doen is om er gewoon op te rekenen dat de eerste kolom uit de DataView de value en de tweede kolom de tekst:

DataView dv = data.GetCategorieen();lstCategorie.DataSource = dv;lstCategorie.DataValueField = dv.Table.Columns[0].ColumnName;lstCategorie.DataTextField = dv.Table.Columns[1].ColumnName;lstCategorie.DataBind();

Je kan hier nog weigerachtig tegenoverstaan, en nog verder willen afsplitsen. Hiervoor kan je:

213

Frank Horemans

Page 214: Cursus ASP.net 1

o Eigenschappen definieëren in de klasse DataObj die de namen van de gewenste velden bevatten.

o In plaats van een DataView te retourneren retourneer je een object dat drie eigenschappen heeft: DataView en twee tekstwaarden

o In plaats van een DataView te retourneren, retouneer je een collectie van objecten uit je eigen klasse.

15.3 3-Tier

Wens je ook nog bedrijfslogica in deze toepassing te verwerken, bijvoorbeeld een korting afhankelijk van de klant, dan kan je werken met een 3-Tier logica.

In deze toepassing vullen we een ListBox met de namen van de klanten. De basis hiervoor is de Stored Procedure KlantenBasis:

Voor de eenvoud plaatsen we de eigenschap AutoPostBack van de ListBox lstCategorie op false, we voorzien een ListBox lstKlant voor de klantenlijst en een Button om de gegevens op te vragen.

CREATE PROCEDURE KlantenBasisASSELECT klant_id, (naam +' ' +voornaam +' (' +convert(varchar(10),klant_id,103) +')') as VolledigeNaamFROM klantORDER BY naam

We maken een nieuwe klassen BusObj aan, deze klasse representeert de Business-Tier of Logische laag

Deze keer communiceren we vanuit de presentatietier enkel met de Business-tier.

214

Frank Horemans

Page 215: Cursus ASP.net 1

De Business-laag bevat logische code om de verkoopprijs te berekenen rekening houdend met een eventuele korting.

De Businesslaag communiceert met de data-tier. De presentatie-tier communiceert niet meer met de data-tier, maar doet dit via de Business-tier

Voor het opvragen van de categorielijst en de klantenlijst doen we nu een aanvraag aan de Business-tier die de aanvraag gewoon doorgeeft aan de data-tier.

Voor het vullen van de DataGrid dgArtikels doen we een aanvraag aan de Business-tier, deze laag doet een aanvraag aan de data-laag en past onze bedrijfscode toe voor het berekenen van de korting.

De data-tier dient enkel aangevuld te worden met de methode GetKlantenBasis.

BusObj.cs

using System;using System.Data;using System.Data.SqlClient;using System.Configuration;

public class BusObj { private DataObj data;

public BusObj() { data = new DataObj(ConfigurationSettings.AppSettings["SpionString"]); }

public DataView GetCategorieen() { return data.GetCategorieen(); }

public DataView GetKlantenBasis() { return data.GetKlantenBasis(); }

public DataView GetArtikelsVoorCategorie(short catid, short klantid) { DataView view = data.GetArtikelsVoorCategorie(catid);

double korting = 0; if ((klantid >= 3)&&(klantid < 5)) { korting = .50; } else if (klantid >= 5) { korting = 1.00; }

for (int i=0; i<view.Count; i++) {

215

Frank Horemans

Page 216: Cursus ASP.net 1

view[i]["Verkoopprijs"] = Double.Parse(view[i]["Verkoopprijs"].ToString()) - korting; }

return view; } }

DataObj.cs

...public DataView GetKlantenBasis()

{ SqlConnection conn = new SqlConnection(_connStr); SqlDataAdapter da = new SqlDataAdapter("KlantenBasis", conn); da.SelectCommand.CommandType = CommandType.StoredProcedure;

DataSet ds = new DataSet(); da.Fill(ds, "KlantenBasis");

return ds.Tables["KlantenBasis"].DefaultView; }

DrieTier.aspx

... public class DrieTier : System.Web.UI.Page { protected System.Web.UI.WebControls.ListBox lstCategorie; protected System.Web.UI.WebControls.ListBox lstKlant; protected System.Web.UI.WebControls.Button Button1; protected System.Web.UI.WebControls.DataGrid dgArtikel; private void Page_Load(object sender, System.EventArgs e) { if (!IsPostBack) { BusObj data = new BusObj(); DataView dv = data.GetCategorieen(); lstCategorie.DataSource = dv; lstCategorie.DataValueField = dv.Table.Columns[0].ColumnName; lstCategorie.DataTextField = dv.Table.Columns[1].ColumnName; lstCategorie.DataBind();

DataView dvK = data.GetKlantenBasis(); lstKlant.DataSource = dvK; lstKlant.DataValueField = dvK.Table.Columns[0].ColumnName; lstKlant.DataTextField = dvK.Table.Columns[1].ColumnName; lstKlant.DataBind(); }

216

Frank Horemans

Page 217: Cursus ASP.net 1

}

...

private void VulArtikels() { BusObj data = new BusObj(); dgArtikel.DataSource = data.GetArtikelsVoorCategorie(Int16.Parse(lstCategorie.SelectedValue),Int16.Parse(lstKlant.SelectedValue)); dgArtikel.DataBind(); }

private void Button1_Click(object sender, System.EventArgs e) { VulArtikels(); } }}

217

Frank Horemans

Page 218: Cursus ASP.net 1

16 WEB SERVICES

16.1 Wat zijn Web Services ?

Een webservice is een klasse die toestaat dat zijn methoden opgeroepen worden vanuit methoden op ander machines. Voor de overdracht van gegevens worden gewone dataformaten zoals XML en protocollen zoals HTTP gebruikt.

Veelal worden deze cross-netwerk aanroepen gedaan via het Simple Object Access Protocol (SOAP), een XML-gebaseerd protocol dat aangeeft hoe request en response moeten opgemaakt worden voor transfer via HTTP.

Web Services vormen de volgende stap in de object-georiënteerde filosofie: in plaats van software te ontwikkelen vanuit een klein aantal klassenbibliotheken die op één locatie staan, hebben programmeurs toegang tot Web Service klassen die wereldwijd toegankelijk zijn.

16.2 Basisbegrippen

Een Web Service is een softwarecomponent, bewaard op een computer, die kan geraadpleegd worden door een applicatie op een andere computer over een netwerk.

De machine die de Web Service huist wordt de Remote Machine genoemd.

16.3 Een Web Service maken: Publishing

16.3.1.1 De Webservice BMI

We maken een eerste webservice: deze service stelt je in staat je lengte en gewicht op te geven en aan de hand hiervoor je Body Mass Index te kennen. Je kan het verkregen getal ook laten evalueren.

16.3.1.2 Een nieuwe Web Service maken in Visual Studio.Net 2010

Maak een nieuwe Solution in Visual Studio 2010: Webservices New Project > Visual C# ASP.NET Empty Web Application

o Name: BMI_Serviceo Solution Name: BMI_Solution

Delete web.config Add > New Item > Web Service: BMI.asmx

BMI.asmx.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Services;

namespace BMI_Service{

[WebService(Namespace = "http://3ejaar.grad.ivo/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.ComponentModel.ToolboxItem(false)]

218

Frank Horemans

Page 219: Cursus ASP.net 1

public class BMI : System.Web.Services.WebService {

[WebMethod] public string EvalueerBMI(Single bmi) { string evaluatie = ""; if (bmi < 5 || bmi > 200) return "U hebt ongeldige gegevens ingevoerd."; else if (bmi <= 17.0) evaluatie = "U hebt een extreem ondergewicht."; else if (bmi <= 20.0) evaluatie = "U hebt een ondergewicht."; else if (bmi <= 25.0) evaluatie = "U hebt een normaal, gezond gewicht ! "; else if (bmi <= 30.0) evaluatie = "U lijdt aan overgewicht."; else if (bmi > 30) evaluatie = "U bent obees."; return evaluatie; }

[WebMethod] public Double BerekenBMI(string gewicht, string lengte_cm) { Single g = 0; Single l = 0;

try { g = Convert.ToSingle(gewicht); l = Convert.ToSingle(lengte_cm); }

catch (Exception e) { return 0.0; } Single lengte_m = l / 100f; Single bmi = g/(lengte_m * lengte_m); return System.Math.Round( bmi,2); } }}

BMI.asmx (Automatisch gegenereerd in VS.Net, openen in bvb. Notepad)

<%@ WebService Language="C#" CodeBehind="BMI.asmx.cs" Class="BMI_Service.BMI" %>

Voer uit!

De browser toont het volgende:

219

Frank Horemans

Page 220: Cursus ASP.net 1

Je kan nu de Methoden van de Web Service testen via pagina's die door het .Net FrameWork op de server werden aangemaakt.

16.4 Werking van de Web Service

16.4.1.1 Web Server

Vooreerst geldt de belangrijke opmerking dat het gebruik van de lokale Web Server van Visual Studio toestaat om lokaal met Web Services te testen, maar om een Web Services bruikbaar te maken van buitenaf moet deze gestuurd worden door een Web Server zoals IIS.

16.4.1.2 Methoden

De methoden in een Web Service die we publiekijk toegankelijk wensen te maken dragen het signatuur [WebMethod].

Webmethoden worden aangeroepen via een Remote Procedure Call (RPC): we roepen een bepaalde functionaliteit aan vanop afstand.

16.4.1.3 Functionaliteit ontdekken

Om de functionaliteit van een Web Service bloot te geven, bevatten Web Services doorgaans een service description. Dit is een XML-bestand dat conform de Web Service Description Language (WSDL) geschreven is.

WSDL-documenten worden doorgaans niet door ontwikkelaars, maar door applicaties die de service wensen te gebruiken, gelezen.

Wanneer de Web Server een request voor een asmx-bestand ontvangt, genereert deze een testpagina voor de webservice. Vanuit deze pagina kunnen we de functionaliteiten van de Web Service onder de loep nemen. Via deze pagina's kan je de WSDL-file ook inkijken (Service Description).

220

Frank Horemans

Page 221: Cursus ASP.net 1

16.4.1.4 SOAP

Het gebruik van deze testpagina's illustreert het gebruik van SOAP requests en responses bij HTTP POST-opdrachten.

SOAP is een platformonafhankelijk protocol dat XML gebruikt om RPC's te maken, standaard over HTTP.

Elk request en response is verpakt in een SOAP-bericht: een XML-bericht met de informatie die de service nodig heeft om het bericht uit te voeren.

Vaak wordt gesproken over een SOAP-enveloppe.

16.5 Een Webservice gebruiken: Consuming

16.5.1.1 Inleiding

Wanneer je rechtstreeks surft naar een asmx-bestand, dan kan je de functionaliteit van een Web Service ontdekken. Het is echter de bedoeling om deze functionaliteit te gebruiken in je toepassingen: vanuit een applicatie ga je de webmethoden aansturen en de resultaten gebruiken.

16.5.1.2 Windows Form toepassing

We maken een kleine WinForm toepassing die onze BMI_Service gebruikt:

Open de solution BMI_Solution, of start gewoon een nieuw project in een andere instantie van VS.Net

Add > New Project Visual c# > Windows > Windows Forms Application Name: BMI_app Add Web Reference...

221

Frank Horemans

Page 222: Cursus ASP.net 1

Bij URL voeg je het adres van je Web Service in zoals in de adresbalk van de browser bij het uitvoeren van BMI.asmx: http://localhost:3418/BMI.asmx

Het poortnummer kan afwijken, daar de interne Web Server zelf een willekeurig poortnummer toegewezen krijgt bij activatie.

Deze URL kan je straks nog wijzigen in de properties van de Web Service

Als Web Reference Name geef je LokaleService op Voeg een Windows Form BMI_Gebruiken toe:

222

Frank Horemans

Page 223: Cursus ASP.net 1

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;

namespace BMI_app{ public partial class BMI_gebruiken : Form { private LokaleService.BMI srvbmi;

public BMI_gebruiken() { InitializeComponent(); }

private void BMI_gebruiken_Load(object sender, EventArgs e) { srvbmi = new BMI_app.LokaleService.BMI(); }

private void BtnBerekenBMI_Click(object sender, EventArgs e) { LblBmi.Text = srvbmi.BerekenBMI(TxtGewicht.Text, TxtLengte.Text).ToString(); LblBeoordeling.Text = srvbmi.EvalueerBMI(Convert.ToSingle(LblBmi.Text)); }

}}

223

Frank Horemans

Page 224: Cursus ASP.net 1

Stel BMI_app in als startup project Voer de toepassing uit!

16.5.1.3 ASP.Net Web Site

Voeg in de solution ...BMI_Solution een New Empty ASP.Net Web Site BMI_site toe

Voeg analoog als hierboven een Web Reference toe Voeg een Web Form BMI_Gebruiken.aspx toe

BMI_Gebruiken.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="BMI_gebruiken.aspx.cs" Inherits="BMI_gebruiken" %>

<!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> Bereken uw Body Mass Index<br /> <br /> <table> <tr> <td style="width: 3px"> Lengte:</td> <td> <asp:TextBox ID="TxtLengte" runat="server"></asp:TextBox></td> </tr> <tr> <td style="width: 3px"> Gewicht:</td> <td>

224

Frank Horemans

Page 225: Cursus ASP.net 1

<asp:TextBox ID="TxtGewicht" runat="server"></asp:TextBox></td> </tr> <tr> <td style="width: 3px"> </td> <td> <asp:Button ID="BtnBerekenBMI" runat="server" OnClick="BtnBerekenBMI_Click" Text="BMI" /></td> </tr> <tr> <td style="width: 3px"> BMI:</td> <td> <asp:Label ID="LblBMI" runat="server" BackColor="#FFFFC0" ForeColor="Blue"></asp:Label></td> </tr> <tr> <td style="width: 3px"> Evaluatie:</td> <td> <asp:Label ID="LblEvaluatie" runat="server" BackColor="#FFFFC0" ForeColor="#C00000"></asp:Label></td> </tr> </table> </div> </form></body></html>

BMI_Gebruiken.aspx.cs

using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;

public partial class BMI_gebruiken : System.Web.UI.Page{ private LokaleService.BMI srvbmi;

protected void Page_Load(object sender, EventArgs e) { srvbmi = new LokaleService.BMI();

} protected void BtnBerekenBMI_Click(object sender, EventArgs e) { LblBMI.Text = srvbmi.BerekenBMI(TxtGewicht.Text, TxtLengte.Text).ToString();

225

Frank Horemans

Page 226: Cursus ASP.net 1

LblEvaluatie.Text = srvbmi.EvalueerBMI(Convert.ToSingle(LblBMI.Text)); }}

Stel BMI_Site in als startup project Voer uit!

16.5.1.4 DISCO: DISCOvery of Web Services

In Solution Explorer kan je voor de Web Site zien dat naast wsdl-file nu ook twee extra bestanden werden aangemaakt: een disco en een discomap-file. Deze twee bestanden zijn gemaakt om clients te wijzen op de locatie van een webservice.

16.6 Werken met verschillende datatypes

Een webservice kan verschillende dataypes retourneren en ontvangen. Binnen .Net kan je op een heel eenvoudige manier deze datatypes in een webservive gebruiken:

Type Beschrijving

Primitief datatype

Standaard primitieve types: String, Char, Byte, Boolean, Int16, Int32, Int64, UInt16, UInt32, UInt64, Single, Double, Guid, Decimal, DateTime (als XML's timeInstant), DateTime (als XML-date), DateTime (als XML-time), and XmlQualifiedName (als XML-QName).

Enumeratie Enumeratietypes, vb. "public enum color { red=1, blue=2 }"

Arrays van primitieven / Enums

Arrays van bovenstaande

Klassen en Structs

Class en struct types met publieke variabelen en eigenschappen, deze worden geserialiseerd

Arrays van Klassen en Structs

Arrays van bovenstaande

DataSet DataSets, of DataSets voorkomend in velden of eigenschappen van

226

Frank Horemans

Page 227: Cursus ASP.net 1

klassen / structs

Arrays van DataSets

Arrays van bovenstaande

XmlNode XML-codefragmenten

Arrays van XmlNodes

Arrays van bovenstaande

227

Frank Horemans

Page 228: Cursus ASP.net 1

16.6.1.1 Variabelen, structs, klassen en Arrays

Maak een Webservice: Datatypes.asmx

Datatypes.cs

using System;using System.Data;using System.Web;using System.Collections;using System.Web.Services;using System.Web.Services.Protocols;

public enum Mode { On = 1, Off = 2 }

public class Order

228

Frank Horemans

Page 229: Cursus ASP.net 1

{ public int OrderID; public double Price; }

[WebService(Namespace = "http://3ejaar.grad.ivo//")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class DataTypes : System.Web.Services.WebService {

[WebMethod] public String SayHello() { return "Hello World!"; }

[WebMethod] public String SayHelloName(String name) { return "Hello " + name; }

[WebMethod] public int[] GetIntArray() { int[] a = new int[5]; for (int i = 0; i < 5; i++) a[i] = i * 10; return a; }

[WebMethod] public Mode GetMode() { return Mode.Off; }

[WebMethod] public Order GetOrder() { Order myOrder = new Order();

myOrder.Price = 34.5; myOrder.OrderID = 323232;

return myOrder; }

[WebMethod] public Order[] GetOrders() { Order[] myOrder = new Order[2];

myOrder[0] = new Order(); myOrder[0].Price = 34.5; myOrder[0].OrderID = 323232;

myOrder[1] = new Order(); myOrder[1].Price = 109.4;

229

Frank Horemans

Page 230: Cursus ASP.net 1

myOrder[1].OrderID = 645645;

return myOrder; } }

Maak een Web-Site Leg een Web Reference DataTypeService naar voorgaande Web Service

Default.aspx

<h4>Datatypes gebruiken met WebServices</h4>

<h5>Methoden die een primitief datatype retourneren (String): </h5> <div id="Message1" runat="server"/>

<h5>Methoden die een array van een primitief datatype retourneren (String): </h5> <div id="Message2" runat="server"/>

<h5>Methoden die een Enum retourneren: </h5> <div id="Message3" runat="server"/>

<h5>Methoden die een Class/Struct retourneren: </h5> <div id="Message4" runat="server"/>

<h5>Methoden die een array van Classes/Structs retourneren: </h5> <div id="Message5" runat="server"/>

Default.aspx.cs

using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page { private DataTypeService.DataTypes d;

protected void Page_Load(object sender, EventArgs e) { d = new DataTypeService.DataTypes();

Message1.InnerHtml = d.SayHello(); Message1.InnerHtml = Message1.InnerHtml +"<p>" +d.SayHelloName("William");

Message3.InnerHtml = Message3.InnerHtml + d.GetMode();

int[] myIntArray = d.GetIntArray();

230

Frank Horemans

Page 231: Cursus ASP.net 1

String myString = "Inhoud van de Array:<BR>"; for (int i = 0; i < myIntArray.Length; i++) { myString = myString + myIntArray[i] + "<BR>"; } Message2.InnerHtml = Message2.InnerHtml + myString;

DataTypeService.Order myOrder = d.GetOrder(); Message4.InnerHtml = Message4.InnerHtml + "<BR>OrderID: " + myOrder.OrderID; Message4.InnerHtml = Message4.InnerHtml + "<BR>Prijs: " + myOrder.Price;

DataTypeService.Order[] myOrders = d.GetOrders(); for (int i = 0; i < myOrders.Length; i++) { if (i > 0) { Message5.InnerHtml += "<BR>"; } Message5.InnerHtml += "<BR>Order#: " + i; Message5.InnerHtml += "<BR>OrderID: " + myOrders[i].OrderID; Message5.InnerHtml += "<BR>Prijs: " + myOrders[i].Price; }

}}

16.7 Toepassing

Toepassing: Filmdatabase

Maak een databasegestuurde Web-Applicatie voor het bekijken van de gegevens uit een filmdatabase: Movie.zip

Vereisten:

Maak een Webapplicatie zoals in volgende schermafdruk

231

Frank Horemans

Page 232: Cursus ASP.net 1

Bij het kiezen van een Letter worden de films getoond die met deze letter beginnen.

Bij het kiezen van een film worden de detailgegevens van een film getoond:

o Titel, o Jaar o Score o De Acteurs volgens de rangschikking in de database

Ontwikkelomgeving: Visual Studio 2005 / Web Developper Express Database: SQL Server 2005 Express De volledige toepassing is AJAX-enabled, voorzie ook een weergave voor de

gebruiker wanneer de toepassing bezig is met verwerken. Werk zoveel mogelijk met centraal bewaarde gegevens: connectiestring, url naar

webservice, ... Werk objectgeoriënteerd volgens dit schema:

232

Frank Horemans

Page 233: Cursus ASP.net 1

233

Frank Horemans

Page 234: Cursus ASP.net 1

234

Frank Horemans