Sunteți pe pagina 1din 337

Copyright 2008 L&S INFO-MAT

Toate drepturile asupra acestei lucrri aparin editurii L&S 1NFO-MAT.


Reproducerea integral sau parial a textului din aceast carte este posibil
doar cu acordul n scris al editurii L&S INFO-MAT.

Tiparul executat la S.C. LuminaTipo S.R.L.


Str. Luigi Galvani nr. 20 bis, Sector 2, Bucureti,
office@luminatipo.com

D escrierea C IP a B ibliotecii N aionale a R om niei

G L A N , C O N S T A N T IN
C urs de C # : program are n V isual C# 2008 Express
E dition / C onstantin G lan, Susana Glan. - B ucureti :
E ditura L & S Info-m at, 2008
ISB N 978-973-7658-16-6

I. G lan, Susana

004.43 C#

Ed itu ra L& S INFO-MAT:


Adresa: Str. Stnjeneilor nr. 6, bl. 30, sc. A, et. 1, apt. 11, sector 4, Bucureti;
Tel/Fax: 031-105.62.84;
Mobil: 0722-530.390; 0722-57.37.01;

E-mail: com enzi@ ls-infomat.ro;


office@ ls-infomat.ro;

Magazin online: www.ls-infomat.ro

Catalog online: www.manuale-de-informatica.ro

Biblioteca Digital de Informatic TUDOR SORIN


www.infobits.ro
3

C UPR IN S
C# i platform a .N E T .................................................................................. 7
.NET Fram ew ork......................................................................................................................................8
Compilarea programelor pe platforma .N E T ................................................................................ 9
Instrumente de dezvoltare a aplicaiilor .N E T ............................................................................ 10
Principalele caracteristici ale arhitecturii .N E T .......................................................................... 10
Mediul Integrat Visual Cri 2008 Express E dition.................................................... ...................... 11
Instalare.............................................................................................................................................11
Compilare n linie de com and.......................................................................................................12
Primul program CU........................................................................................................................... 12
O scurt analiz a programului salut.cs......................................................................................... 14
Crearea unei aplicaii de tip consol............................................................................................. 14
IntelliSense - o facilitate important a editorului de c o d .......................................................... 16
Rezumatul capitolului............................................................................................................................ 17
ntrebri i e x erc iii............................................................................................................................... 17

Lim bajul C# . In tro d u cere .................................................................................... 18


Structura unui program simplu C # ..................................................................................................... 18
O aplicaie de tip C onsol................................................................................................................18
Metoda M ain - punctul de intrare n aplicaie............................................................................ 19
Calificarea complet a numelor cu ajutorul operatorului ........................................................ 20
Parametri n linia de com and.............................................................................................................21
Variante ale metodei M a in ...................................................................................................................23
Rezumatul capitolului........................................................................................ 24
ntrebri i e x erc iii............................................................................................................................... 24

Fundam entele lim bajului C # ................................................................................ 25


T ipuri........................................................................................................................................................ 25
Tipuri predefinite..............................................................................................................................25
Tipuri definite de program ator................:......................................................................................27
Tipuri vaioare i tipuri referin.....................................................................................................29
Conversii ntre tipuri........................................................................................................................ 31
Variabile i constante............................................................................................................................32
Enumerri.................................................................................................................................................33
E xpresii....................................................................................................................................................34
T ablouri.................................................................-.................................................................................. 36
Tablouri unidim ensionale............................................................................................................... 36
Tablouri m ultidim ensionale............................................................................................................38
Tablouri neregulate...........................................................................................................................39
Instruciuni...................................................................................... 2..................................................... 42
Instruciunea de selecie i f ... e ls e ................................................................................................ 42
Instruciunea de selecie s w i t c h ................................................................................................. 43
Ciclul f o r ......................................................................................................................................... 44
Ciclul f o r e a c 'n ...............................................................................................................................44
Ciclul w h i l e .....................................................................................................................................45
Ciclul d o w h i l e ............................................................................................................................46
Instruciuni de salt necondiionat...................................................................................................46
Spaii de num e........................................................................................................................................ 48
Directive de preprocesare.....................................................................................................................51
Directiva # d e f i n e ......................................................................................................................... 52
Directiva S u n d e f i n e ....................................................................................................................52
4 C# p en tru liceu Cuprins

Rezumatul capitolului............................................................................................................................ ^
ntrebri i ex erciii..............................................................................................................................." J

P rogram are O rientat pe O biecte n C # ..........................................................


Obiecte i clase........................................................................................................................................^
Mecanismele fundamentale ale OO P................................................................................................
Clasele CU................................................................................................................................................56
Definirea claselor...............................................................................................................................57
Metode. Parametrii m etodelor......................................................................................................... 59
Suprancrcarea m etodelor...............................................................................................................65
Membrii statici ai unei c la se ........................................................................................................... 64
C onstante............................................................................................................................................ 65
C onstructori........................................................................................................................................ 66
Cuvntul cheie t h i s ........................................................... 69
Destructorul c la se i.............................................................................................................................51
Proprieti............................................................................................................................................71
Indexatori.............................................................................................................................................56
Operatori de conversie......................................................................................................................58
Clase interioare.................................................................................................................................. 80
C oninere.............................................................................................................................................82
Clase p ariale ......................................................................................................................................83
Clase sigilate....................................................................................................................................... 84
Suprancrcarea operatorilor................................................................................................................. 84
Sintaxa................................................................................................................................................. 85
Suprancrcarea operatorilor binari................................................................................................85
Metoda T oStringO ............................................................................:............................................... 87
Suprancrcarea operatorilor unari................................................................................................. 87
Structuri.....................................................................................................................................................89
Interfee.....................................................................................................................................................90
M otenire.................................................................................................................................................. 92
Specializare i generalizare..............................................................................................................92
Implementarea m otenirii................................................................................................................93
Accesarea membrilor m otenii......................................................................................................95
Constructorii claselor d erivate........................................................................................................ 97
Membrii ascuni................................................................................................................................. 99
Polim orfism ............................................................................................................................................ 100
Conversia referinelor..................................................................................................................... 100
M etode virtuale.................................................................................................................................101
Utilitatea polim orfism ului.............................................................................................................. 104
Rezumatul capitolului........................................................................................................................... 105
ntrebri i ex erciii.............................. 105

T rsturi eseniale ale lim bajului C # ...............................................................t06


D elegri................................................................................................................................................... 106
Declarare............................................................................................................................................ 106
Crearea obiectelor delegare............................................................................................................ 106
Invocarea metodelor ataate unei deiagri..................................................................................107
Invocarea delegrilor cu tipuri de retur...................................................................................... 108
Evenim ente........................ 109
Lucrul cu evenimente.......................................................................................................................109
Publicarea evenimentelor n mod specific .NET 1i 2
G enerice ................................................................................................................................................ 114
Clase generice................................................................................................................................... 115
C# pentru liceu C uprins 5

Metode generice................................................................................................................................117
C olecii.................................................................................................................................................... 119
Clasa generic S t a c k < T > ............................................................................................................ 119
Clasa generic L i s t < T > .............................................................................................................. 120
Clasa generic D i c t i o n a r y C T k e y , T v a l u e > .................................................................121
Tratarea excepiilor................................................................................................................................123
Manevrarea stringurilor........................................................................................................................124
Operaii i m etode............................................................................................................................ 125
Formatarea stringurilor................................................................................................................... 125
Transformarea stringurilor n valori num erice........................................................................... 126
Citirea unui ir de valori num erice ..................................................................................... 127
Citiri i afiri din fiiere de tip tex t.................................................................................................. 128
Rezumatul capitolului........................................................................................................................... 130
ntrebri i e x erc iii...............................................................................................................................130

A plicaii de tip W indow s F o r m s ........................................................................ 131


Aplicaii cu interfa grafic cu utilizatorul......................................................................................131
Realizarea unei aplicaii simple de tip W indows Form s................................................................132
Controale, proprieti i evenim ente.................................................................................................. 134
Tratarea evenim entelor.........................................................................................................................135
Cum se creaz handier-ele............................................................................................................. 135
O privire n spatele scenei...............................................................................................................138
Declanarea programatic a unui evenim ent...............................................................................142
Crearea programatic a unui control............................................................................................ 143

C ontroalele W indow s F orm s............................................................................... 145


Controlul B utton.............................................................. a........................ 145
Controalele Labei i LinkL abel.......................................................................................................... 148
Controalele RadioButton, CheckBox i G roupBox........................................................................ 151
Controlul T extBox................................................................................................................................. 154
Controalele MenuStrip i ContextM enuStrip.................................................................................. 161
F orm e....................................................................................................................................................... 165
Principalii membri ai clasei Form ................................................................................................. 165
Crearea form elor............................................................................................................................... 166
Dialoguri modale i dialoguri ncm odale......................................................................................167
Butoane de validare a datelor......................................................................................................... 173
Dialoguri predefm ite.............................................................................................................................177
Descrierea dialogurilor predefm ite............. ,............................................................................... 177
Afiarea dialogurilor predefm ite................................................................................................... 178
MDI - Multiple Document Interface................................................................................................. 184
Controlul RichT extB ox........................................................................................................................ 191
Controlul ToolTip.................................................................................................................................. 196
Controlul N otifylcon............................................................................................................................ 199
Fonturi..................................................................................................................................................... 203
Stilurile F onturilor...........................................................................................................................204
Fonturile instalate............................................................................................................................ 206
Desenarea fo nturilor....................................................................................................................... 206
T abC ontrol............................................................................................................................................. 208
Controalele ListBox, ComboBox i CheckedListBox...................................................................213
Controalele TrackBar, NumericUpDown i D otnainU pD ow n...................................................218
Controlul ProgressB ar..........................................................................................................................223
Controlul T im er..................................................................................................................................... 224
Controalele PictureBox i Im agelist..................................................................................................227

.... -*
III < nil 1'i i 1
6 C# p en tru liceu Cuprins C a p ito lu l!. C# i platform a .N E T 7

Controlul ListV iew ............................................


Controlul TreeV iew ...........................................
P artea f
Controalele Web Browser i StatusStrip.......
Integrarea W indowsMediaPIayer n aplicaii Limbajul C#
D esenare n .N E T cu V isual C # .......................................................................... 260
Clasa Graphics....................................................................................................................................... 260
Penie pentru desenarea form elor......................................................................................................260 Capitolul 1
Pensule pentru umplerea form elor.................................................................................................... 264
Desenarea textului................................................................................................................................ 266
C# i platforma .NET
X M L cu C # ................................................................................................................270
Sintaxa X M L ......................................................................................................................................... 270
Clase .NET pentru X m l....................................................................................................................... 271 Numele limbajului C# a fost inspirat din notaia tt (diez) din muzic, care
Citirea informaiilor dintr-un document XM L................................................................................ 271 indic faptul c nota muzical urmat de jt este mai nalt cu un semiton. Este o
Descrcarea fiierelor XML de pe Internet......................................................................................275 similitudine cu numele limbajului C++, unde ++ reprezint att incrementarea unei
Citirea i analiza unui document XML cu X m ITextReader........................................................ 276 variabile cu valoarea 1, dar i fptui c C++ este mai mult dect limbajul C.
Crearea coninutului XML cu Xm lTextW riter............................................................................... 279 Limbajul C# a fost dezvoltat n cadrul Microsoft. Principalii creatori ai
limbajului sunt Anders Hejlsberg, Scott Wiltamuth i Peter Golde. Prima
B aze de date i A D O .N E T . N oiuni introductive......................................... 282 implementare C# larg distribuit a fost lansat de ctre Microsoft ca parte a
Instrumente de lucru.............................................................................................................................282
iniiativei .NET n iulie 2000. Din ace! moment, se poate vorbi despre o evoluie
Calitile SG D B R -urilor................................................................................................................ 283
spectaculoas. Mii de programatori de C, C++ i Java, au migrat cu uurin spre
Furnizori de baze de date relaionale.......................................................................................... 284
Tehnologia ADO.NET - introducere............................................................................................... 284 C#, graie asemnrii acestor limbaje, dar mai ales calitilor noului limbaj. La
Caracteristicile tehnologiei AD O .N ET ...................................... 284 acest moment, C# i-a ctigat i atrage n continuare numeroi adepi, devenind
Arhitectura AD O .N ET....................................................................................................................285 unul dintre cele mai utilizate limbaje din lume.
Crearea unei baze de date n V C S E .............................................................................................288 Creatorii C# au intenionat s nzestreze limbajul cu mai multe faciliti.
Interogri cu Query Designer........................................................................................................ 292 Succesul de care se bucur n prezent, confirm calitile sale:
Controlul DataGridView................................................................................................................ 299
Este un limbaj de programare simplu, modern, de utilitate general, cu
A p licaii cu baze de date n m odelul conectat.............................................. 304 productivitate mare n programare.
U tilizarea provider-ului pentru SQL Server 2005 ......................................................................... 304
Este un limbaj orientat pe obiecte.
Utilizarea provider-ului pentru OLE D B ......................................................................................... 309
Permite dezvoltarea de aplicaii industriale robuste, durabile.
Utilizarea provider-ului pentru O D B C .............................................................................................312
Ofer suport complet pentru dezvoltarea de componente software,
A p licaii cu baze de date n m odelul deconectat..........................................320 foarte necesare de pild n medii distribuite. De altfel, se poate
Construirea i utilizarea dataset-urilor..............................................................................................320 caracteriza C# ca fiind nu numai orientat obiect, ci i orientat spre
Accesarea tabelelor ntr-un dataset....................................................................................................321 com ponente.
Accesarea rndurilor i coloanelor ntr-o tabel................. :................................ 321
Accesarea valorilor dintr-o tabel a unui dataset................................................... 322 La aceste caracteristici generale se adaug i alte trsturi, cum este de
Propagarea schimbrilor din dataset spre baza de date................................................................. 322 pild suportul pentru internaionalizare, adic posibilitatea de a scrie aplicaii care
Dataset-urile i X M L ............................................................................................................................326 pot fi adaptate cu uurin pentru a fi utilizate n diferite regiuni ale lumii unde se
Controalele i legarea d a te lo r.............................................................................................................327
vorbesc limbi diferite, fr s fie necesare pentru aceasta schimbri n arhitectura
Legarea simpl a datelo r................................................................................................................ 327
software.
Legarea complex a d a te lo r.......................................................................................................... 328
n strns legtur cu A rh ite ctu ra .NET (.NET Fram ew ork) pe care
R elaii n tre ta b e le ...................................................................................................335 funcioneaz, C# gestioneaz n mod automat memoria utilizat. Eliberarea
Constrngerea Cheie Strin-Cheie P rim ar...................................................................................335 memoriei ocupate (garbage collection) de ctre obiectele care nu mai sunt
Interogri. Proceduri stocate............................................................................................................... 338 necesare aplicaiei, este o facilitate important a limbajului. Programatorii nu mai
Vederile unei baze de date (V iew s).................................................................................................. 346 trebuie s decid singuri, aa cum o fac de pild n C++, care este locul i
B ibliografie........................................................................................................................................... 351 momentul n care obiectele trebuie distruse.
n C# se scriu ce asemenea aplicaii pentru sisteme complexe care
funcioneaz sub o mare varietate de sisteme de operare, ct i pentru sisteme
8 Partea I. L im bajul C#

dedicate (embeded systems). Acestea din urm se ntind pe o arie larg, de la


dispozitive portabile cum ar fi ceasuri digitale, telefoane mobile, MP3 playere, pn
la dispozitive staionare ca semafoare de trafic, sau controlere pentru
automatizarea produciei.
Din punct de vedere sintactic C# deriv din limbajul C++, dar include i
influene din alte limbaje, mai ales Java.

.N E T F ram ew o rk

A rh ite c tu ra .N ET este o component software care ofer un mediu de


programare i de execuie a aplicaiilor pentru sistemele de operare Microsoft. Este
inclus n sistemele de operare Windows Server 2008 i Windows Vista i poate fi
instalat pe Windows XP i Windows Server 2003.
.NET F ra m e w o rk este un mediu care permite dezvoltarea i rularea
aplicaiilor i a serviciilor Web, independente de platform.
Limbajul C# se afl ntr-o strns legtur cu arhitectura .NET. Iniial, C# a
fost dezvoltat de ctre Microsoft pentru crearea codului platformei .Net, la fel cum
destinaia iniial a limbajului C a fost aceea de a implementa sistemul de operare
UNIX. .NET pune la dispoziie o colecie impresionant de clase organizate n
biblioteci, pe care C# le utilizeaz.
Este momentul s precizm c C# funcioneaz avnd .NET ca
infrastructur, dar .NET suport i alte limbaje, cum este C++, Visual Basic sau
Java. n oricare dintre aceste limbaje programai, avei la dispoziie aceleai
biblioteci de clase. .NET se realizeaz n acest fel in te ro p e ra b ilita te a lim bajelor.

.NET este constituit din dou entiti importante:

C om m on Language R untim e (CLR)


Acesta este m e d iu l de execuie al programelor. Este modulul care
se ocup cu managementul i execuia codului scris n limbaje
specifice .NET. CLR furnizeaz de asemenea servicii importante,
cum sunt securitatea aplicaiilor, portabilitatea acestora,
managementul memoriei i tratarea excepiilor.

* Base Class L ib ra ry
Este vorba despre Biblioteca de Clase .NET. Aceast bibliotec,
acoper o arie larg a necesitilor de programare, incluznd
interfaa cu utilizatorul, conectarea cu bazele de date i accesarea
datelor, dezvoltarea aplicaiilor web, comunicarea n reele i altele.
Codul bibliotecii este precompilat, fiind ncapsulat de regul n
funcii, numite metode, pe care programatorul le poate apela din
propriul program. La rndul lor, metodele aparin claselor, iar
clasele sunt organizate i separate ntre ele cu ajutorul spaiilor de
nume (namespaces). Despre toate aceste noiuni vom vorbi pe larg
n capitolele urmtoare. Ceea ce trebuie reinut pentru moment,
este c programatorii combin propriul cod cu codul Bibliotecii de
Clase .NET pentru producerea de aplicaii.
C a p ito lu l!. CU i p la tfo rm a .N E T 9

C o m p ila re a p ro g ra m e lo r pe platfo rm a .N E T

Limbaje interpretate
Cnd programai ntr-un limbaj de programare interpretat, vei scrie codul i
vei rula aplicaia. Cu ajutorul unui interpretor specific limbajului, fiecare linie de cod
este interpretat chiar n momentul rulrii i este preschimbat imediat n cod
main i executat. Partea bun este c putei rula codul pn la primul bug,
putei nltura eroarea n cod iar apoi s continuai execuia codului. Limbajul nu
necesit timp de compilare i de legare. Partea neplcut este c limbajele
interpretate sunt lente. Limbajul Basic a fost iniial un limbaj interpretat, dar mai
apoi, ncepnd cu anii 1980, au aprut i versiuni compilate. Marea majoritate a
limbajelor de scriptare Web sunt de asemenea limbaje interpretate.

Limbaje compilate
Codul scris ntr-un asemenea limbaj, numit cod surs, este translatat de
ctre compilator ntr-un cod apropiat de nivelul mainii, numit cod executabil (de
exemplu codul coninut n fiierele (*.exe). Dac n timpul compilrii apar erori,
atunci este necesar s le nlturai, dup care vei compila din nou. Dac aplicaia
trece acum de compilare fr erori de sintax, atunci se va produce codul
executabil i vei putea s rulai aplicaia. Limbajele C i C++ sunt exemple clasice
de limbaje compilate.
Din aceast perspectiv C# este un limbaj compilat. Dar nu n sensul descris
mai sus. Ca s nelegei, este necesar s tii c n urma compilrii unui program
C#, nu se creaz un cod executabil. Se creeaz un fiier numit a s s e m b ly care de
regul se identific cu extensia .exe sau .d!l. Un asemenea fiier nu poate fi
executat pe un sistem pe care nu exist infrastructura .NET. Fiierul conine un tip
special de cod, numit L im b a j Interm ediar, pe scurt CIL (Common intermediate
Language). Limbajul CIL definete un set de instruciuni portabile, independente
de orice tip de procesor i platform.
Figura ilustreaz procesul de creare a codului executabil pe platforma .NET.

Cod surs
C# C om pilator C# .Net

Cod surs
C om pilator J# .Net
,J# C IL i com pilare
m etadate cu J I T
(.exe i .dll) i execuie
Cod surs C om pilator C++.Net r
C!

Cod surs C om pilator VB .Net


VB

Fig. 1.1 Procesul de compilare pe platforma .NET


,y'iiiii'ii iiini'-rrrf ....
T(TT " T arfefl/ Limbajul C#
... ; ------------------------------------------------------------

- n momentul Tri" rare un program este executat, CLR activeaz un


compilator special, numit JIT {just in time). Acesta preia codul CIL i l transform
n cod executabil. Transformarea se face la cerere, n sensul c o secven de
rad se.,compileaz doar n momentul n care este utilizat pentru prima oar. Un
program, compilat n format CIL poate rula pe orice sistem pe care s-a instalat
Commori Language Runtime. Aceasta asigur portabilitatea aplicaiilor .NET.
Fiierul .exe sau .dl! produs la compilare conine pe lng codul CIL, aa
numitele metadate. Metadatele descriu datele utilizate de ctre aplicaie.

Instrumente de dezvoltare a aplicaiilor .NET


Platforma .NET actual a ajuns la versiunea 3.5. Microsoft pune la dispoziia
programatorilor dou unelte pentru dezvoltarea aplicaiilor:

1. Visual Studio .NET i varianta free Visual Studio Express 2008.


2. .NET Framework SDK.

Pachetul de dezvoltare a aplicaiilor pentru .NET 3.5 (Microsoft .NET


Framework 3.5 SDK1), include:
> .NET Framework
> Compilatorare n linie de comand pentru limbajele de
programare: C#, C++ , Visual Basic, i Jscript..
> Instrumente pentru crearea, depanarea i configurarea aplicaiilor
.NET.
> Exemple i documentaie.

Trebuie s tii c exist compilatoare pentru platforma .NET create de anumite


firme sau organizaii, pentru limbajele Smaltalk, Perl, Cobo! sau Pascal, ca s
enumerm doar cteva disponibile pe pia.

Principalele caracteristici ale arhitecturii .NET

Independena de procesor i de platform


Codul CIL este independent de sistemul de operare i de procesor.
De aceea, n scrierea aplicaiilor nu trebuie s fii preocupai de caracteristicile
hardware sau software ale sistemului. Spre surpriza multor programatori, aplicaiile
.NET pot fi dezvoltate i executate pe sisteme de operare non-Microsoft, (Mac OS
X, numeroase distribuii Linux i Solaris, ca s numim numai cteva).
Managementul automat al memoriei
Alocara i eliberarea memoriei nu mai este o problem care trebuie s-i
preocupe pe programatori, datorit mecanismului automat de garbage collection.
Interoperabilitatea limbajelor
Este un fapt comun ca diversele componente ale unei aplicaii s fie scrise
n limbaje diferite, suportate de ctre platforma .NET.

1Sof t war e De v e l op me n t Ki t - K. i l de D ezvoltare a A plicaiilor


C apitolul 1. C# i p la tfo rm a .N E T 11

Securitate
.NET furnizeaz un model comun de securitate, valabil pentru toate
aplicaiile, care include un mecanism unificat de tratare a excepiilor. O excepie
este un eveniment neprevzut, care ntrerupe execuia unui program, atunci cnd
de pild, se execut o intruciune ilegal.
Portabilitate
Un program scris pentru platforma .NET poate rula fr nici o modificare pe
oricare sistsm pe care platforma este instalat.
Caracteristicilor de mai sus li se adaug i altele, care ies ns din cadrul
acestei lucrri.

M ediul In teg ra t Visual C# 2008 E xpress Edition

Visual C# 2008 Express Edition (pe scut: VCSE), este un mediu free de
dezvoltare a aplicaiilor produs de Microsoft. Este un IDE (integrated development
environment), care ofer un set de instrumente, ntre care un editor de cod pentru
scrierea programelor C#, compilator, depanator, instrumente pentru build
automation (automatizarea procesului de compilare) i altele. Kit-ul de instalare C#
Express, include Platforma .NET 3.5, iar aceasta la rndul ei include ntre altele
Biblioteca de Clase.

Cerine de sistem
Sistemele de operare suportate sunt: Windows Server 2003, Windows Vista',
Windows XP.

> Pentru Microsoft Windows XP, Service Pack 2


minim 192 MB de RAM (preferabil cel puin 384 MB)
cel puin un procesor de 1 GHz (preferabil > 1.6 GHz)
> Pentru Microsoft Windows Vista i Microsoft Windows Server 2003
minim 768 MB de RAM (preferabil cel puin 1 GB)
cel puin un procesor de 1,6 GHz (preferabil > 2.2 GHz)

instalare
Visual C# 2008 Express Edition poate fi descrcat de pe site-ul Microsoft,
ia adresa http://www.microsoft.com/express/download/. Alternativ, n josul paginii
avei opiunea de a descrca Visual Studio Express Edition pentru o instalare
offline. Visual Studio conine mediile de programare Visual C#, Visual Basic,
Visual C++, precum i serverul de baze de date Microsoft SQL Server 2005.
Instalarea se face simplu, cu ajutorul unui wizard, ns pentru montarea imaginii
DVD-ului (fiier cu extensia ISO) avei nevoie de un utilitar cum ar fi de pild
Daemon Tools.
Ca observaie, indiferent dac vei instala Visual Studio sau doar Visual C#
2008 Express, vei opta ntotdeauna pentru instaiarea .NET Framework, Visual
C#, MS SQL Server i MSDN (Micorsoft Developer Network). MSDN conine o
foarte bogat documentaie de care nu v putei lipsi cnd dezvoltai aplicaii.
12 Partea I. L im bajul C#

Exist i versiunile Visual C# 2008 i Visual Studio 2008 cu faciliti suplimentare,


dar care nu sunt gratuite.
Ajuni n acest punct, dorim s atragem atenia asupra faptului c o
prejudecat rspndit privind dezvoltarea .NET este aceea c programatorii
trebuie s instaleze Visual Studio ca s poat crea aplicaii C#. Nu este adevrat.
Putei s compilai i s rulai orice tip de program .NET folosind kit-ul de
dezvoltare a aplicaiilor .NET Framework 3.5 Software Development K it (SDK),
care este downloadabil n mod gratuit. Acest SDK v pune la dispoziie
compilatoare, utilitare n linie de comand, conine Biblioteca de Clase .Net,
exemple de cod i o documentaie complet.
Se pot crea aplicaii C# n dou moduri diferite:
1. Folosind Notepad sau oricare editor de text i apoi compilarea n linie de
comand.
2. Utiliznd Visual Studio Express Edition. Aceasta este metoda preferabil,
datorit sprijinului considerabil pe care-l ofer mediul integrat n
dezvoltarea aplicaiilor, mai ales a acelora cu interfa cu utilizatorul.

Compilare In linie de comand


Dei s-ar putea ca niciodat s nu v decidei s dezvoltai aplicaii mari
folosind compilatorul C# n linie de comand, este totui important s nelegei
cum se lucreaz n linie de comand fie doar i pentru urmtoarele motive:
Nu avei o copie a Visual C# 2008 Express, sau.sistem ul pe care-nu
satisface cerinele hardware sau software minimale:
Dorii s proiectai un b uild tool automatizat, aa cum este MSBuild sau
Nant, care necesit s cunoatei opiunile n linie de comand ale
utilitarelor.
Dorii o nelegere profund a C#, dorii s vedei ce se petrece n
spatele scenei atunci cnd utiiizai IDE-uri pentru dezvoltarea aplicaiilor.

Primul program C#
Este o tradiie pstrat n timp, ca o carte de programare s nceap cu
programul care afieaz pe ecran s a l u t lu m e ! Vom compila i executa acest
program C# n linie de comand, urmnd paii de mai jos:

1. Editarea codului surs

Deschidei Notepad i scriei urmtorul cod:


u s in g S y s te m ;
c la s s S a lu t
(
s t a t i c v o i d M a in ()
{
C o n s o le . W r i t e L i n e ( " S a lu t lu m e 1" ) ;
}
}
C apitolul 1. C# i pla tfo rm a .N E T 13

n C# fiierele surs au extensia cs. Salvai fiierul cu numele sa lu t.cs ntr-un


folder oarecare, de exemplu C:\teste.

2. Compilarea n linie de comand


La promptul de comand, compilai astfel: esc sa lu t.cs

Aadar, compilatorul csc.exe (C sharp compiler) primete ca argument n linie


de comand numele fiierului surs. Vei constata c n urma compilrii, n
folderul C:\teste s-a creat fiierul salut.exe. Acesta este un a ssem bly,
coninnd codul intermediar CiL. Executarea lui este posibil doar pe
sistemele care au infrastructura .NET.

3. E xecutarea p rog ra m u lu i
Rularea programului se face simplu, prin tastarea numelui fiierului .exe:

c:\teste>salut

Programul afieaz:
Salut l u m e !

Setarea va ria b ile i de m ediu PATH


Dac platforma .NET a fost instalat odat cu Visual Studio sau VCSE,
atunci la instalare putei opta ca variabila de mediu PATH s rein n mod implicit
cile spre utilitarele n linie de comad. inclusiv spre compilator, ceea ce v
scutete de efortul de a ie introduce manual. Dac PATH nu reine aceste ci,
atunci nu vei putea lucra n linie de comand, deoarece sistemul de operare nu va
gsi aceste utilitare.
14 Partea I. L im bajul C#

n cazul n care nu ai ales varianta setrii PATH la instalare, o putei face


ulterior astfel:
La promptul de comand, mutai-v n subdirectorul Common7\Tools al
instalrii.
Rulai fiierul de comenzi VSVARS32.bat scriind: v s v a r s 32.

O scurt analiz a programului salut.cs


Prima linie a programului, u s in g S y s te m ; spune implementrii C# prin
intermediul directivei using, c se vor utiliza clase aflate n spaiul de nume
System. Aa cum vei vedea n capitolul urmtor, C# a preluat din C++ spaiile de
nume (namespaces). Spaiile de nume funcioneaz ca nite containere, n care se
definesc nume de clase pentru evitarea conflictelor de nume, dar i pentru
separarea logic. Toate clasele din Biblioteca de Clase .N E T se definesc n
interiorul unor spaii de nume. System este un spaiu de nume fundamental, care
definete ntre altele, clasa C onsole. Aceasta din urm, conine metode (funciile
din C#) care scriu i citesc date de la consol.
Observm c la fel ca n C++, exist metoda Main(), care se declar
ntotdeauna static.

important ' * * * *
,0 deosebirffa d e 'C + i este faptul'c trebuie s existe n cjiail
de fa clasa S a ltf care gzduiete metoda Mainf). Aceast, degai^ce'C# ^ste
un lim b a j p u r o rientat obiect, i riti pci exista deftniii de funcii fn.aknra claselor

n acest sens, C# seamn cu Java. Totui, n Java numele clasei care conine
metoda main() trebuie s coincid n mod obligatoriu cu numele fiierului. Dac
vei schimba mai sus numele clasei, de exemplu Hello, o s constatai c nu vei
avea nici o problem la compilare.
Linia Console.WriteLine("Salut lume!"); este apelul metodei
statice WriteLine din clasa Console. O s revenim asupra metodelor statice n
capitolele urmtoare. Pentru moment, reinei c o metod static se apeleaz
astfel: nume clasa.nume metod.

Crearea unei aplicaii de tip consol

1. Deschidei mediul integrat de programare: Start->AII Programs-> Visual C#


2008 Express Edition.
2. n meniul File, selectai New Project. Se deschide dialogul New P roject.
Acesta permite alegerea diferitor tipuri de aplicaii. Selectai Console
Application ca tip de proiect i schimbai numele aplicaiei n salut. Click OK.
Visual C# Express Edition 2008 creaz un nou folder pentru proiect, cu
acelai nume cu cel al proiectului. Deschide de asemenea fereastra principal
i Editorul de Cod unde vei intra i vei modifica codul surs C#.
C apitolul 1. C# iplatform a .N E T 15

Visual Studio installed templates

Windows Class Lit<rary W Pf W PF Browser E Z 3 S H &TlPi:>' Project


Forms A... Appfcation Acc*caticn

M y T e m p la te s

S earch O n tn e
Tem plates...

A project for creating a command-ire application {.NT Framework 3.5)

Name: sakit

| OK 1 ! C a re d

u s in g S y s te m ;
' u s in g S y s te m .C o lle c tio n s .C e n e ric ;
! u s in g S y s te m .L ir.q ;
u s in g S y s te m .T e x t;

n am esp ace s a lu t
' {
j c la s s -
{
j: s ta tic v o i d M a in ( s c r ir .g [) a rg s)
| {
: )
)
16 Partea I. L im bajul C#

B arele de in s tru m e n te (Toolbars) sunt n partea de sus a ferestrei j


principale. Acestea conin icon-uri pentru crearea, ncrcarea i salvarea j
proiectelor, editarea codului surs, compilarea aplicaiei. Accesare: V iew - i
>Too!bars. n partea a doua a lucrrii, prin T o o lb a rv o m identifica bara de
intrumente care pstreaz iconuri cu controalele Windows Forms.
S o lu tio n E xp lo re r este un panou foarte util care afieaz fiierele care \
constituie proiectul. Cel mai important fiier este P rogram .es," care
conine codul surs al aplicaiei. I

3. Este permis s schimbai numele clasei n E d ito ru l de C od. De exemplu J


schimbai Program cu Salut. |

4. Scriei codul de mai jos :


t :
J
using System; f

static void Main(string[] args) l


( i
Console.WriteLine("mi place C# !");
Console.ReadLine(); !
} ;

5. Rularea programului.
Programul este gata de compilare i rulare. Se apas F5 ori click pe iconul ^

IntelliSense - o facilitate important a editorului de cod


Cnd se scrie un nume sau un cuvnt cheie n editor, se poate utiliza 1
instrumentul numit IntelliS ense care este parte a panoului de cod. De exemplu, 1
cnd metoda ReadLine apare evideniat n list, Apsai Enter sau Tab sau !
facei dublu-ciick i ReadLine va fi adugat n cod: ]
C apitolul 1. C# i p la tfo rm a .N E T 17

Avantajul utilizrii IntelliS ense este pe de o parte faptul c programatorul nu


trebuie s memoreze toate tipurile i metodele vizibile ntr-un anumit context
deoarece acestea apar n mod automat n list. Pe de alt parte, poate fi sigur c
ceea ce scrie este corect.

R ezum atul capitolulu i

C# este un limbaj din familia C++, orientat pe obiecte, cu mare productivitate n


programare.
Infrastructura pe care se programeaz n C# este .NET Fram ew ork.
.NET F ram ew ork este un mediu care permite dezvoltarea i rularea aplicaiilor
i a serviciilor Web, independente de platform.
. Una dintre componentele de baz a .NET Framework este B ib lio te c a de
Clase .NET.
Mediul Visual C# Express Edition 2008 este un instrument de programare free,
cu care putei dezvolta aplicaii pentru sistemele de operare Windows.

ntrebri i exerciii

1. Precizai cteva dintre calitile limbajului C#.

2. Ce reprezint Common Language Runtime ?

3. Descriei modul n care se produce compilarea unui program C#. Care


este rolul compilatorului J IT ?

4. Ce este un asse m bly ?

5. Descriei cteva dintre caracteristicile Platformei .NET.


18 Partea I. L im bajul C#

C apitolul 2

Limbajul C# . Introducere
Limbajul C# este deosebit de simplu, cu numai 80 de cuvinte cheie i 12
tipuri incorporate. Dar C# este n acelai timp un limbaj foarte productiv din punct
de vedere al programrii aplicaiilor i pe deplin adaptat conceptelor moderne de
programare.
Fiind un limbaj orientat pe obiecte, o caracteristic esenial a sa este
suportul pentru definirea i lucrul cu clasele. Clasele definesc tipuri noi de date.
Variabilele de tip clas se numesc obiecte. Uneori un obiect este abstract, cum ar fi
o tabel de date sau un thread (program sau proces lansat n execuie). Alteori
obiectele sunt mai tangibile, cum sunt un buton sau o fereastr a aplicaiei.
Obiectele sunt un element fundamental n programare datorit rolului lor n
modelarea problemelor din practic care trebuie rezolvate. Programarea orientat
pe obiecte se sprijin pe trei piloni fundamentali: ncapsularea datelor, m o te n ire
i p o lim o rfis m .
Clasele C# conin c m p u ri i p ro p rie t i care rein informaii despre obiecte
i m e to d e (funcii aparinnd clasei). Metodele ncapsuleaz cod care descrie ceea
ce poate face obiectul, aciunile i capabilitile sale. Obiectele la rndul lor,
interacioneaz, comunic ntre ele.
C# este un limbaj care ofer suport explicit pentru tratarea eve n im e n te lo r.
Vom reveni pe larg asupra tuturor acestor concepte n capitolele urmtoare.
C# admite program area generic. Programarea generic este un stil de
programare diferit de programarea orientat pe obiecte. Scopul programrii
generice este scrierea de cod care s fie independent de tipul datelor. De exemplu,
imaginai-v o funcie care primete ca parametru un ir numeric pe care l
sorteaz. Algoritmul de sortare nu depinde de tipul elementelor irului. Acestea pot
fi de pild ntregi sau reale. n aceast situaie n C# putei defini o funcie
generic, care va folosi dup caz, iruri ntregi sau reale.
C#, aa cum s-a vzut n capitolul precedent utilizeaz un garbage
c o lle c to r (colector de deeuri) pentru eliberarea memoriei ocupate de obiectele de
care aplicaia nu mai are nevoie. Obiectele C# se aloc ntotdeauna dinamic, adic
n timpul execuiei programaului i se distrug n mod automat.

S tructura unui p ro g ra m sim plu C#

O aplicaie de tip Consol

Creai n VCSE o aplicaie de tip consol i rulai programul urmtor:

/*
Programul declarar variabile, iniializeaz
variabile i face atribuiri
*/
C apitolul 2. L im b a ju l C#. Introducere 19

namespace SpatiulMeu
{
class Test
{
static void Main(string[] args)
{
int a; // Declararea unei variabile locale
a = 20; // Atribuire
double b = 10; // Declarare i iniializare
string s = "obiect de tip string";

System.Console.WriteLine("a = " + a ) ;
System.Console.WriteLine("b = " + b ) ;
System.Console.WriteLine("s este " + s ) ;
}
}
}

Cu Ctrl + F5 compilai i lansai programul, care va afia pe ecran:

a = 20
b = 10
s este obiect de tip string

Vom analiza n continuare structura acestui program.

Metoda M a in - punctul de intrare n aplicaie


Fiecare program necesit un punct de intrare (entry point) i n cazul C#,
aceasta este metoda static Main. La lansarea n execuie a programului, mediul
de execuie .NET (CLR) caut i apeleaz metoda Main. Un program poate s
conin mai multe clase, dar numai una dintre acestea definete metoda Main.

Tipuri abstracte
Programul declar un tip (clasa cu numele Test) i un membru al clasei
(metoda Main). Este o diferen fa de C++, unde de regul tipurile abstracte se
declar n fiiere header, iar definiiile acestora n fiiere .cpp separate.

Variabile locale
Metodele unei clase pot s declare variabile locale, aa cum este variabila
ntreag a, variabila real b i variabila de tip string, s. Tipul string este un tip
definit n Biblioteca de Clase .NET, fiind destinat lucrului cu iruri de caractere.
Variabilele locale pot fi iniializate cu valori la momentul declarrii.

Comentarii
C# admite comentarii multilinie ( / * ... * / ) i comentarii de o singur linie
( I I ), ntocmai ca C++.
20 Partea I. L im bajul C#

Clase |
C# lucreaz cu clase. Fiind un limbaj pur orientat obiect, nu putei scrie un 5
program C# fr clase. Totul se petrece n interiorul claselor. Tot ceea ce aparine I
unei clase, va fi definit n interiorul ei. Nu exist variabile globale i nici funcii |
globale. Un program trebuie s aib cel puin o clas, aceea care conine metoda |
M a in . O clas se definete cu ajutorul cuvntului cheie c la s s . j
Exemplu: f

class Persoana
t *
{ I
// membrii clasei v

}
Observaie: I
Programatorii C++ trebuie s fie avizai de faptul c n C# dup ultima j
parantez nchis a clasei, nu se pune ; . j
4
Spaii de nume definite de programator \
Exist spaii de nume predefinite. Ne referim la acelea care fac parte din I
Biblioteca de Clase .NET. n acelai timp C# permite programatorilor s-i creeze !
propriile spaii de nume pentru organizarea logic a aplicaiilor mari. Ai remarcat I
desigur namespace SpatiulMeu definit n primul program. Este bine de reinut i
c prezena lui este opional i c att clasa care conine metoda Main, ct i !
celelalte clase ale programului pot s fie incluse sau nu n interiorul unui I
namespace. I
j
Calificarea complet a numelor cu ajutoruloperatorului . j
Afirile pe ecran s-au fcut prin apelul metodei statice writeLine din |
clasa Console. Clasa Console este definit n spaiul de nume System. Pentru
utilizarea claselor C# din Biblioteca de Clase .NET, dar i a metodelor statice ale j
acestor clase, exist alternativele: |
1. Utilizarea directivei using; !
Directiva using face vizibile n program toate numele de clase dintr- j
un spaiu de nume. Reamintim c spaiile de nume sunt containere logice j
care servesc la separarea numelor de tipuri ntr-o bibliotec de clase sau j
ntr-un program. f
Exemple: |
using System; - toate numele definite n spaiul de nume |
System devin accesibile. |
~
using System.Windows.Forms - clasele din spaiul de nume \
Forms devin vizibile n program. Observai c spaiile de nume se I
pot include unele n altele. De pild System conine mai multe f
clase, dar i spaii de nume printre care spaiul de nume Windows, j
Spaiul de nume Windows la rndului lui inciude mai multe spaii 1
de nume, ntre care i Forms.
C apitolul 2. L im b a ju l C#. In troducere 21

2. Calificarea complet a numelui


Calificarea complet a numelui (fully qualified name) presupune
precizarea cii complete pn la numele metodei. n programul anterior,
apelul System. Console .WriteLine ("a = + a); ilustreaz modul
corect de apelare. Operatorul . servete la separarea spaiilor de nume.
Se pornete de la spaiul de nume exterior (System) i se continu cu
specificarea tuturor spaiilor de nume pn se ajunge la metoda dorit.
S scriem dou programe simple:

// P rim u l p ro g ra m fo lo s e te d ire c tiv a using


using System;

class Test
{
static void Main()
{
Console.WriteLine("C#");
1
}

// A l d o i le a p ro g ram p r e c iz e a z c a le a c o m p le t
// a n u m e lu i m e to d e i
class Test
{
static void Main()
{
System,Console.WriteLine("C#");
>
}

Cele dou programe compileaz i ruleaz identic.

Param etri n linia de com and

Metoda M a i n poate avea un parametru. Acesta este un ir de stringuri, care


reine argumentele n linia de comand care se transmit programului. Acestea sunt
informaii care pot fi pasate programului de ctre utilizator. Creai un proiect de tip
consol cu numele arg. n editorul de cod introducei programul:

u s i n g S y s te m ;
c la s s P ro g ra m
t
s t a t i c v o id M a i n ( s t r i n g [] arg s)
{
fo r ( i n t i = 0 ; i < a r g s .L e n g t h ; i+ + )
C o n s o le .W r ite ( a r g s [ i] + " " ) ;
}
1
22 Partea I. L im bajul C#

Compilai proiectul (facei Build) cu F6. n fotderul \bin\Release al aplicaiei se va


produce fiierul assem biy cu numele arg.exe.

OBSERVAII
Vom reveni n capitolul urmtor asupra buclei for. n acest moment reinei
sintaxa preluat din limbajul C.
Length este o proprietate public a clasei abstracte Array, care returneaz
numrul de elemente ale irului. Toate tablourile unidimensionale din C#
motenesc clasa Array, deci pot utiliza proprietile acesteia.

Transmiterea argumentelor de la promptul sistemului de operare


Interpretorul n linie de comand al sistemului de operare este cmd.exe.
Acionai Start->Run i introducei comanda cmd. La promptul sistemului
schimbai calea n folderul \bin\Release al proiectului. Tastai numele programului,
urmat de cateva argumente separate prin spaii: arg unu doi trei patru.
Programul afieaz pe ecran: unu doi trei patru

Argumentele sunt de regul informaii de care programul are nevoie, de


exemplu numele fiierelor de intrare i de ieire.

Transmiterea argumentelor n linie de comand din Visual C# Express


n fereastra Solution Explorer, facei dublu click pe iconul Properties. n
fereastra din dreapta, click pe tab-ul Debug. Introducei argumentele n linie de
comand n TexfBox-ul cu eticheta Command Line Arguments:
a rg * Program, cs Start Page '
. .... .
Application
Start Options --------------- -------- ..... .......... - - . - ----
Build , Command line arguments', a B C D E|

Suild E vents | |
Debug*
Working directory: I
j Q
Re so u rces 3 Enable the Visual Studio hosting process

Settings

Facei B u ild i rulai acionnd Ctrl + F5. Programul afieaz: a b c D e


C apitolul 2. L im baju l C#. Introducere 23

Variante ale m eto dei M ain


La crearea unei aplicaii de tip consol, VCSE genereaz urmtoarea
definiie pentru metoda Main:

static void Main (string[] args) { /*...*/}

Este declarat static, are tipul de retur void i un ir de stringuri, ca i


parametru de intrare. C# admite i alte signaturi ale funciei Main, ca mai jos:

static int Main (stringf] args) { /* ...* /} / / Tip de retur int,


I I un ir de stringuri ca argument
static void Main() { /* ...* /} / / Fr tip de retur, fr argumente

static int Main() { /* ...* /} // Tip de retur int, fr argumente

Vei alege un prototip sau altul, n funcie de necesiti. Dac dorii ca aplicaia s
ntoarc sistemului de operare o valoare ntreag, de pild un cod de eroare cnd
programul se termin, atunci vei prefera o signatur care returneaz int. Dac
aplicaia folosete argumente transmise de ctre utilizator din linie de comand,
atunci vei opta pentru o versiune cu un parametru de tip ir de stringuri.

IMPORTANT
r- C# este case-sensitive. Aceasta nseamn c M a in este corect, iar m a in greit, c
W r i t e L i n e nu este tot una cu w x i t e l i n e .

> Cuvintele cheie din Cit, (retum , i n t , v o i d , i f , etc) se scriu cu litere mici.

> Pentru tipurile definite de programator, pentru spaiile de nume i pentru metode,
exist convenia p e care este indicat s o respectai i anume: prim a liter este
mare i fiecare cuvnt coninut ncepe tot cu liter mare.
Exemple: Console .ReadLine () - metod
System.Time Zone - spaiu de nume
System.Data. SqlClient - clas

Rolul cuvntului cheie static n prototipul metodei Main


Main este membr a unei clase, de pild clasa TestAfisare. Dar o clas
nu este altceva dect o specificaie a unui tip de date. n lipsa unui obiect de tip
TestAfisare, nu exist nici un membru al clasei. Totui, Main trebuie s fie
apelat pentru c este punct de intrare n program. Pentru ruperea cercului vicios,
se definete Main ca metod static. Metodele statice au tocmai aceast
proprietate interesant, c ele exist i pot fi apelate n lipsa unui obiect de tipul
clasei.
a. juimuajUl C#

Accesul public sau privat Ia metoda Main


La fel ca n cazul altor limbaje orientate obiect, n C# se specific modul de
acces la membrii clasei cu ajutorul modificatorilor de acces public sau private.
Vom reveni n capitolul urmtor asupra acestor cuvinte cheie. Pe scurt, cuvntul
private aplicat unui membru de clas face ca acel membru s nu poat fi
accesat din exteriorul clasei. Visual C# 2008 Express definete mod implicit
metoda Main ca fiind private, pentru ca alte aplicaii s nu o poat apela. Avei
libertatea s specificai modificatorul public sau private. Construciile urmtoare
sunt legale:

public static void Main)


{
)

private static void Main()


{
}

R ezu m atul cap ito lu lu i

Metoda Main este punctul de intrare ntr-un program C#.


* Un program trebuie s aib cel puin o clas, aceea care conine metoda
Main.
Main are cteva versiuni. Prin tabloul de stringuri pe care Main l are ca
parametru, se pot pasa programului argumente n linia de comand.
C# nu admite variabile globale. Toate v&riabilele declarate sunt locale.
Toate clasele .NET sunt definite n interiorul unor spaii de nume.

ntrebri i exerciii

1. Ce se nelege prin garbage c o lle c tio n 2

2. Care este rolul cuvntului cheie static n signatura metodei Main ?

3. Ce se nelege prin fully qualified name ?

4. Scriei un program C# care se ruleaz ntr-o aplicaie de tip consol.


Programul afieaz toi parametrii transmii n linie de comand. Nu se vor
utiliza directive de compilare.

5. Ce rol are operatorul . ntr-un program C# ?


C apitolul 3. F undam entele lim baju lui C# 25

Capitolul 3

Fundamentele limbajului C#
Acest capitol descrie elemente de baz ale limbajului C#: tipurile de date,
sintaxa, expresiile, operatorii, directivele de procesare.
Toate programele din acest capitol se pot testa cu ajutorul unei aplicaii de tip
consol n Visual C# 2008 Express Edition.

Tipuri

C# este un limbaj puternic tipizat (strongly-typed). Un asemenea limbaj


impune programatorului s declare un tip pentru fiecare obiect creat, iar
compilatorul verific compatibilitatea dintre tipurile obiectelor i valorile care le sunt
atribuite.

T ipu rile siste m din C#, se mpart n dou categorii:


Tipuri predefinite (built-in), cum sunt int,char, etc.
Tipuri definite de programator (user-defined). Acestea se definesc cu
ajutorul claselor, structurilor sau interfeelor.

Un alt sistem de clasificare a tipurilor n C# mparte tipurile astfel:


Tipuri referin
Tipuri valoare

Tipurile valoare sunt variabile locale care se memoreaz n segmentul de stiv al


programului, iar tipurile referin se aloc dinamic n Heap.
C# admite i tipul pointer, ns pointerii sunt folosii foare rar i doar n
situaiile cnd se lucreaz cu unmanaged code, adic cod nespecific platformei
.Net.

Tipuri predefinite
C# ofer toate tipurile de baz necesare unui limbaj de programare modern.
In C# toate tipurile sunt obiecte, chiar i cele mai elementare tipuri. Cuvintele cheie
pentru tipurile predefinite (int, char, double, etc.) sunt mapate direct peste tipuri
struct din spaiul de nume System. De exemplu, cuvntului cheie int i
corespunde clasa System. Int32 din Biblioteca de Clase .NET. Avei libertatea s
declarai o variabil ntreag astfel:

System.Int32 x; , n loc de int x;

Maparea tipurilor primitive peste tipuri din .NET asigur faptul c tipurile create n
C# pot interaciona cu tipuri create n alte limbaje care lucreaz pe platforma .Net.
Tipurile referin predefinite sunt object i string.
a
t<
' i;
26 Partea I. L im bajul C#

Tipul o b j e c t |
Tipul object este rdcina ntregii ierarhii de tipuri i clasa de baz a 1
tuturor claselor din .NET Fram ew ork. Aceasta nseamn pe de o parte c toate |
clasele din .NET motenesc clasa object i pe de alat parte c oricare clas |
definit de programator deriv n mod implicit din object. f

Tipul s t r i n g
Tipul s t r i n g reine un ir de caractere din setul Unicode. Unicode este un
standard care permite reprezentarea tuturor caracterelor scrise n orice limb
scris, nu doar n limbile de circulaie internaional (n jur de 100.000 carcatere).

T abelul 3.1 T ip u ri C# p re d e fin ite


Tip Dimensiune T ip .Net Descriere
(bytes) asociat
object variabil Object Tipul de baz al tuturor tipurilor
string variabil String Tip ir de caractere.
byte 1 Byte Tip ntreg fr sem n. [0, 255]
char 2 Char Tip caracter. Reine carcatere U nicode
bool 1 Boolean V alori tr u e sau false
sbyte 1 SByte Tip ntreg cu semn. f-128, 127]
short 2 intl6 Tip ntreg cu semn. f-32768, 32767]
ushort 2 UIntl6 Tip ntreg fr semn. [0, 65535]
int 4 Int32 Tip ntreg cu semn.
f-2.147.483.648, 2.147.483.647]
uint 4 Uint32 Tip ntreg far semn. [0, 4.294.967.295]
float 4 Single Tip real cu virgul m obil, sim pl precizie.
Valori cuprinse ntre +/-1,5 x IO-45 i +/-3,4
x 1038 cu 7 cifre sem nificative
double 8 Double Tip real cu virgul m obil, dubl precizie.
Valori cuprinse ntre + /-5,0 x 10'324 i + /-1 ,8
x IO308 cu 15 cifre sem nificative
decimal 12 Decimal T ip zecim al cu virgul fix. Precizie de cel
puin 28 cifre sem nificative.
long 8 Int64 Tip ntreg cu semn. [-263, 263 - 1]
ulong 8 UInt64 Tip ntreg far semn. [0, 2 54]
' >!
|
ii
Tipul decimal se folosete n calcule financiare, atunci cnd erorile de rotunjire
& i datorate virgulei mobile sunt inacceptabile.

. Declarri de variabile
I
Toate declarrile de mai jos sunt legale:

object ol, o2 = nuli;


string s = "Salut";
sbyte b = 6;
short h = 13;
C apitolul 3. F undam entele lim bajului C# 27

ushort u = 7;
int a = 10;
long p = 3, q = 8L;
ulong x = 2UL, y = 5L, z = 10U, w = 8;
float fl = -4.5, f 2 = 3.8F ;
double dl = 1.3, d2 = 0.2 D ;
char c = 'T /
D e c i m a l d = 12.4M; // m desemneaz o constant decimal

Tipuri d efinite de p ro g ra m a to r

n C# programatorii pot defini propriile tipuri cu ajutorul cuvintelor cheie :


class, struct, interface, delegate i enum. Tipul tablou este de asemenea
un tip user-defined.

Tipul class

n C# clasele se creeaz cu ajutorul cuvntului cheie class:

class nume c l a s a
(
m o d i f i c a t o r _ a c c e s T i p num e_m em bru;
// a li m em b ri
}

Exemplu:

class ntreg
{
public int x; // x - c m p (m e m b ru ) al c la s e i

De re in u t:
Variabilele de tip clas se numesc obiecte sau instane ale clasei.
Crearea unuiJobiect de tip clas, se numete instaniere.

Instanierea se face cu ajutorul operatorului new, urmat de apeiui constructorului


clasei. Vom reveni asupra acestor noiuni n capitolul urmtor. Vom crea dou
obiecte de tip ntreg:

ntreg r l , r 2 ; // D e c l a r d o u r e f e r i n e
rl = new ntreg(); // C r e e a z u n o b i e c t r e f e r i t d e rl
r2 = new ntreg(); // C r e e a z u n o b i e c t r e f e r i t d e r2

Mai sus, rl i r2 se numesc referine.


28 C apitolul 3. F undam entele lim bajului C# 29
Partea I. L im bajul C#
class TestStruct
IM P O R T A N T {
Accesarea membrilor clasei se face cu sintaxa: referina .membru static void Main()
{
// D a t e l e o b i e c t u l u i p s e m e m o re a z n s t i v
Modificatorul public care prefixeaz declararea cmpului x, indic faptul c Persoana p = new Persoana();
poate fi accesat din afara clasei sale astfel: r . x. p .nume = "Iul ia";
Ilustrm aceste informaii n programul i n t r e g . cs: p.varsta = 8;
C o n s o l e .Write ( " N u m e le { 0 } \ n V a r s t a (1} a n i " ,
u s in g S y s te m ; p.nume, p.varsta);
}
class ntreg
}
{
public int x; La rulare, programul afieaz:

Numele Iulia
class Testlntreg Varsta 8 ani
{
static void Main() N ot
{ Metodele Write i WriteLine din clasa Console, admit formatarea
ntreg r = new ntreg(); afirii n maniera funciei printff) din C. Modificatorii {0} i {1}
r.x = 10; // A t r i b u i e v a l o a r e a 10 c m p u l u i x specific locul i ordinea n care se vor afia valorile argumentelor
C o n s o le . W r i t e ( r . x ) ; / / A f i e a z 10 p.nume, respectiv p .varsta.
}
} \n este o secven escape, reprezentnd caracterul (newline).

Observai c un program C# poate s conin una sau mai multe clase, dintre care
una singur conine metoda Main. Tipuri valoare i tipuri referin

Structuri n C# tipurile se clasific n tip uri valoare i tip uri referin.


Tipurile valoare sunt toate tipurile predefinite (char, int, float, etc.), cu
Structurile se construiesc prin utilizarea cuvntului cheie struct. Au fost
excepia tipurilor string i object. C# permite n plus definirea de tipuri valoare
introduse n C# pentru a permite programatorului s defineasc tipuri valoare. Sunt
cu ajutorul cuvntului cheie struct. Tipurile valoare se caracterizeaz prin faptul
similare claselor, dar le lipsesc unele caracteristici, cum ar fi motenirea. Obiectele
c se memoreaz n segmentul de stiv al programului.
de tip struct se depoziteaz n stiv. Se creeaz i se acceseaz mai rapid
Tipurile referin, se definesc de ctre programator. n aceast categorie se
dect ceie alocate dinamic. Sunt de preferat atunci cnd avei nevoie de obiecte
mici ca dimensiuni, sau care se construiesc ntr-un ciclu. includ tipurile clas, tipurile interfa, tipurile delegat i tipurile array (tablourile). Se
Sintaxa este similar cu cea a claselor: numesc tipuri referin, deoarece variabilele folosite pentru manipularea lor sunt
referine la obiecte alocate dinamic n Heap. O variabil de tip referin, pstreaz
Exemplu de fapt adresa obiectului din Heap pe care l refer, astfel c exist o asemnare
ntre referine i pointerii C++.
u s in g S y s te m ; Ca s putem lmuri pe deplin diferenele ntre tipurile referin i tipurile valoare,
vom vedea cum se creaz obiectele.
Struct Persoana
{ IMPORTANT
public string nume; Tipurile valoare difer de tipurile referin prin faptul c variabilele de
public int varsta; tip valoare conin datele obiectului, n timp ce variabilele de tip referin conin
referine la obiecte.

Pentru a lmuri aceasta, vom analiza programul:


30 Partea I. L im bajul C#

class C // Tip referin


{
}

struct S // Tip valoare


{
}

class StackHeap
{
static void Main(string[] args)
{
irit x = 7; // V a r i a b i l l o c a l .
S 3 = new S(); // s - v a r i a b i l l o c a l

C r; // R e f e r i n a r s e m e m o r e a z p e Stiv,
r = new C(); // A l o c n Heap u n o b i e c t r e f e r i t d e

Unde se vor memora variabilele x, s, r i obiectele create cu new ? Privii figura:

Figura 3.2. Memorarea datelor tipurilor valoare i referin |

Observm cteva aspecte importante: I

Obiectul cu numele s de tip struct, creat cu new sememoreaz n |


stiv. I
Referina r la obiectul de tip class se memoreaz n stiv, iar obiectul f
propriuzis creat cu new se aloc n Heap. f
Variabila x se memoreaz n stiv. I
C apitolul 3. F undam entele lim bajului C# 31

de REINUT:

> Datele variabilelelor de tip valoare, se memoreaz pe stiv (Stack). O


excepie de la aceast regul o constituie situaia n care tipuri valoare
sunt incorporate unui tip referin (de pild, sunt date membre ale unei
clase), n acest caz datele se memoreaz n Heap.
> n cazul tip u rilo r referin, referinele sunt n stiv, iar datele se aloc
dinamic n Heap.

Conversii n tre tipuri

Obiectele de un anume tip se pot converti n obiecte de un alt tip n mod implicit
sau explicit. Tipurile predefinite suport de asemenea conversii.

Conversiile implicite
Acest tip de conversie se produce n mod automat. O face compilatorul i
avei garania c se produce fr pierdere de informaie.

Exemplu:

ahort a = 4 ;
int n = a; // Conversie implicit spre tipul int.
II Nu s e p i e r d e in fo rm a ie

Conversiile explicite
Dac ncercai s atribuii unei variabile de tip short valoarea unei variabile
de tip int, compilatorul nu va efectua conversia implicit, deoarece aceasta poate
cauza pierdere de informaie. Avei totui posibilitatea de a efectua aceast
conversie cu ajutorul operatorului de conversie explicit (cast operator) :

int n = 10000;
short sl = n; I I Incorect. Nu v a c o m p i l a
short s2 = (short)n; I I Corect.Conversie explicit
II cu p i e r d e r e de in fo rm a ie

Secvena urmtoare ilustreaz modul n care conversiile au loc n C#:

// D e c la r ri
object o = nuli;
int a = 2000;
short b = 3 ;
char c = 1T ';
long d = 10;
double f = 1.2;
// T e s ta re a c o n v e rtib ilit ii
a = d; I I Eroare.
a =(int)d; II Corect. Conversie explicit
o = b; I I Corect. T o a t e t i p u r i l e se c o n v e rte s c
II i n m od i m p l i c i t l a t i p u l object
b = o; I I Eroare.
C apitolul 3. F undam entele lim bajului C# 33
32 Partea I. L im bajul C#

f = b; // Corect. Conversie implicita


b = f; // Eroare, Enum erri
ulong e = -3; // Eroare. Enumerrile sunt tipuri de date de tip valoare, create de programator n
a = c; // Corect. Conversie implicita I scopul de a grupa sub un nume un set de constante simbolice.
c = a; // E r o a r e .
C = (char)a; // Corect. Conversie explicit
I Exemplul 1:

I
|u s i n g S y s te m ;
Variabile i co nstante
* enura S aptamana
Variabile I (
Luni, M a r t i , Miercuri, Joi ,
O variabil este o locaie de memorie care are un tip asociat. n programul Vineri, Sambata, Duminica
de mai jos, a i b sunt variabile:

u s in g S y s te m ;
class TestEnum

static void Main (string [] args)


!{
static void Main()
{
int a = 2; i < Saptamana ziua = Saptamana.L u n i ;
int b; if ( ziua == Saptamana.Luni)
b = 3;
l C o n s o le .W r ite ( " L u n i e (0 ) M a rti e (1 } ",
S y s t e m . C o n s o l e . W r i t e L i n e (a + " " + b) ; | (int)Saptamana.Luni, (int)Saptamana.Marti);
}
>
Programul afieaz: 2 3
Comentai instruciunea b = 3 ; Vei constata faptul c programul are o eroare. ^Programul afieaz: Luni e 0 Marti e l
Compilatorul anun c ai ncercat s utilizai o variabil creia nu i-a fost atribuit 1
o valoare.
[De reinut:
Membrii unei enumerri se numesc enumeratori. Lista membrilor
IMPORTANT enumerrii, se separ prin virgul.
C# nu permite utilizarea variabilelor crora programul nu le-a asociat anterior o Variabila ziua de tip enum, reine doar unul dintre membrii enumerrii
valoare. I (Luni).
I Valorile membrilor enumerrii se obin prin conversii explicite la int i sunt
Constante | egale cu 0 ,1 , 2, ... , dac nu se specific alte valori pentru enumeratori.
O constant este o variabil iniializat, a crei valoare nu mai poate fi
modificat n program. Constantele se introduc cu ajutorul calificativului const: |Exemplul 2
| Membrilor unei enumerri li se pot asocia valori de tip ntreg:
1
u s i n g S y s te m ;
s t a t i c v o i d M a i n ( s t r i n g [] a rg s) fu s in g S y s te m ;
{ tenum Note
const long x = 100; // Corect
ft
const string s; / / Eroare. C o n s t a n t a n e in itia liz a ta
s = " S a lu t" ; I Mate = 10,
S y s te m .C o n s o le .W r ite L in e ( x + " + s ) | Xnfo = 9,
} Romana = 8
Programul nu va compila, deoarece stringul s a fost declarat constant dar nu i s-a
atribuit o valoare iniial.
C apitolul 3. Fundam entele lim bajului C# 35
34 P artea I. L im bajul C#
Aditivi + - x+y x-y A d u n a r e , s c d e re
class TestEnum Shiftare X y D e p la s a r e p e b ii la s t n g a
X y i la d re a p ta
{
static void Main() x<y x>y x<=y x>=y

A
"Relaionali i

II

It I
O p e r a to r i a ritm e tic i
{ de testare a is X is T trua, dac x este
{. l } \ n r o m a n a :
Con s ol e . W r i t e ( " m a t e : { O i \ n i n f o : (2)'
tipului c o n v e rtib il la T. A ltfe l,
(int)Note.Mate, (int)Note.Info, (int)Note.Romana) false
as X as T R e tu m e a z x c o n v e rtit la
1
T s a u nuli d a c
c o n v e rs ia e im p o s ib il
Programul afieaz: Eqalitate == != X y x ! =y E g a i i d if e r it
AND logic & X 4 y A N D lo g ic p e bii
A X " y
mate: 10 XOR logic X O R lo g ic p e bii
info: 9 OR logic I X I y O R lo g ic p e bii
ro m a n a : 8 AND && X SS y E v a lu e a z y n u m a i d a c x

constantele. Utilizare^ condiional e s te true


Enumerrile sunt o alternativ puternic n raport cu OR II X Il y E v a lu e a z y n u m a i d a c x
enumerrilor face codul mai clar, mai bine documentat. condiional e s te false
Condiional ? : X ? y : z E v a lu e a z y d a c x e s te
true. A ltfe l, e v a lu e a z z
Atribuire = *= /= = y x %= y
E x p re s ii I X A tr ib u ir e s im p l i
%= += etc. a trib u ir i c o m p u s e
Expresiile n C# sunt similare cu expresiile din C++ i Java. Expresiile s$ = &= A=
valoare n urrm
construiesc folosind operanzi i operatori i n general ntorc o ' " ' !=
de metode, de tablouri, de
evalurii lor. Operanzii sunt variabile de memorie, n mot-
obiecte, etc.
prezint operatorii C# n ordinea descreterii p r e c e d e n i Observaie:
Tabelul de mai jos | Hin tabel
Din tahp se constat c apelurile metodelor sunt expresii, accesarea unui
(prioritii) lor. ii
| element ntr-un tablou este o expresie, crearea de obiecte sau de tablouri sunt de
I asemenea expresii.
T abelul 3.3. Operatorii C#
-g Cnd o expresie conine mai muli operatori, precedena operatorilor
Expresii Descriere I determin ordinea de evaluare a operaiilor.
Grupul de O perator
operatori - De exemplu, x - y / z se evalueaz ca x - (y / z) deoarece precedena
A c ce s la m em brii clasei
| operatorului / este mai mare dect cea a operatorului - .
A p e l d e m e to d Cnd un operand se gsete ntre doi operatori cu aceeai preceden,
f (x)
A c c e s la e le m . ta b lo u r ilo r f..atunci asociativitatea operatorilor controleaz ordinea operaiilor.
[] a[x]
x++
P o stin c re m e n tare | n afara operatorilor de atribuire, toi operatorii binari se asociaz de la
P o std ec re m e n ta re festnga spre dreapta. De exemplu: a + b + c se asociaz (a + b) + c.
Primari new T(x) C r e a r e d e o b ie c te | Operatorii de atribuire i operatorul condiional (? :) se asociaz de la
new T[x] C r e a r e d e ta b lo u ri
______ -|dreapta spre stnga. De exemplu: a = b = c se evaluaeaz n ordinea a = (b
typeof t y p e o f (T) Inform aii despre tipul T ^
checked checked (x) E v a le a z e x p r e s ia x n | Precedena i asociativitatea se pot controla cu ajutorul parantezelor. De
unchecked u n c h e c k e d (x)
unrA ecw '* ' |exemplu: a+b/c mparte b la c i apoi adun a la rezultat, dar (a+b) /c adun a
i mparte rezulatul la c . ( [ 1] )
Unari
N e g a ie lo g ic
N e g aie pe bii
++x P reincrem entarc
X P red ecrem en tare
(T)x C o n v ersie explicita
*y x/y X%y n m u lir e , m p rire ,
M ultiplicativi
m o d u lo ________ __
36 Partea I. L im bajul C# C apitolul 3. F undam entele lim bajului C# 37

IMPORTANT !
Tablouri Tablourile sunt n realitate o b ie cte care motenesc clasa Array. De aceea,
metodele i proprietile acestei clase pot fi folosite pentru tablouri. Proprietatea
Un tablou este o structur de date coninnd variabile de acelai tip. n C#g ^ g c la s e iA r returneaz numrul de elemente ale tabloului
tablourile sunt tipuri referina. Tablourile pot fi unidimensionale sau| __________________ _______________
multidimensionale. Cele multidimensionale, la rndul lor pot fi dreptunghiularei
sau neregulate (ja g g e d). | Exemplul 2:
Mai jos, a, b, c, sunt tablouri de double, char, string, respectiv obiecte
Tablouri unidimensionale de tip A.

* class TabUnidim2
Declararea tablourilor unidimensionale se face preciznd un tip de dat_
urmat de operatorul de indexare i numele tabloului. Crearea tabloului se face cu |
class A
new urmat de tip i dimesiunea tabloului cuprins ntre paranteze ptrate.
{
}
Declarare: T i p [ ] a ;
Creare: a = new Tip[n] ; static void Main()
{
Tablourile se indexeaz de la 0. Un tablou cu n elemente este indexat de la 0 la n-f doublet] a = new double[100];
1. char[] b = new char[50];
string[] s = new string[1000];
Exemplul 1:
Programul de mai jos definete un tablou cu 5 valori de tip I n t . // Tablou de 7 obiecte de tip A
A [] ob = new A [7 ] ;
using System; for (int i = 0; i < ob.Length; i++)
if ( ob[i] == null ) //
class TabUnidiml Console.Write("null ");

static void Main() Decimal[] d = new Decimal[10]


{ for (int i = 0; i < d.Length; L+ + )

// Tablou cu 5 elemente de tip int Console.Write(d[i] + " "),


int[] a; // Declarare )
a = new i n t [5]; // Creare
for (int i = 0; i < a.Length; i++)
a[i] = i + 1; Programul afieaz:

for (int i = 0; i < a.Length; i++) null null null null null null null 0 0 0 0 0 0 0 0 0 0
Console.W r i t e (" a [{0}] = (l}\n", i, a[i](
Observaii:
1. C# v permite s definii clase imbricate (nested), aa cum este cazul
clasei A, definit n interiorul clasei TabUndim2 .
Programul afieaz: 2. Valorile implicite ale tablourilor numerice sunt setate la 0, iar elementele
referin sunt setate la nuli.
a[0] = l
a[l] = 2
a [2] = 3
finiialjalizare
a [3] = 4
a [4] = 5 Tablourile unidimensionale se pot iniializa cu valori de acelai tip cu tipul
Ijtabloului:
38 P artea I. L im bajul C# C apitolul 3. F undam entele lim bajului C# 39

E xem plu :
Exemple:
I using System;
// Tablou cu 4 elemente.
int[] a = new int[] { 7, 4, 3, 0 };
class TabBidim
// Sintax alternativ. Tablou cu 3 elemente {
i n t [] b = {10, 2, 17};
static void Main()
{
float[] c = { 1.2F, 7.9F, -8F };
int[,] y;
s t r i n g [] sl = new string[] { "UNU", "DOI", "TREI" }, // y = { { 1, 2, 3 }, { 2, 3, 0 } }; // Ilegal

i n t [,] x ;
// Sintax alternativ. Tablou cu 3 elemente
3 tring[]s2 = { "UNU", "DOI", "TREI" }; x = new i n t [, ] { { 1, 2, 3 }, { 2, 3, 0 } } ; / / OK

for (int i = 0; i < 2; i++)


(
Tablouri multidimensionale for (int j = 0; j < 3; j++)
Console.Write(x[i, j] + " ");
Un tablou poate avea una, dou sau mai multe dimensiuni. Console.WriteLine() ;

Exemple:
I)
// Tablou bidimensional cu 3 linii i 5 coloane
d o u b l e [,] a = new d o u b l e [3, 5 ] ; ! Ieire:

// Tablou tridimensional cu dimensiunile 3, 7 i 5 1 - 3


|!2 3 0
d o u b l e [, ,] a = new d o u b l e[3, 7, 5] ;

Accesarea elem entelor ^


Accesarea elementelor unui tablou multidimensional se face cu sintaxjTablouri n e reg u late
cunoscut din limbajul Pascal. De exemplu, elementul aflat pe linia 2 i c o lo a n a |
ntr-o matrice se acceseaz astfel: a [2 , 0 ]. Un tablou neregulat (jagged array) este un tablou ale crui elemente sunt
|tablouri. Elementele pot fi tablouri unidimensionale sau chiar multidimensionale.
Iniializare .
Tablourile multidimensionale pot fi iniializate ca n exemplele urmtoare: |tx e m p lu :
| Un jagged array cu dou elemente, fiecare dintre acestea fiind un ir de
/ / Tablou cu 2 linii i 3 coloane | i n t , se declar astfel:
i n t [,] x = new i n t [, ]{ {1 , 2 , 3 },{ 2, 3 , 0 } };
|int[] [] a = new int [2] [] ;
// Identic, dar cu sintaxa alternativa |
int[,] y ={ { 1 , 2, 3 } , { 2 , 3, 0 } }, |Tablul nu este nc completdefinit. Este nevoie de iniializarea fiecrui element'
I
DERETINUT ... = new int[3]; // tablou unidimensional cu 3 elemente
D a c creat mai nti referina, iar tabloul va_ficreatulterior, atunci sintaxa [i] = new int[5]; // tablou unidimensional cu 5 elemente
a i

alternativ de iniializare nu se mai poate folosi. n acest caz este obiigatoiL


utilizarea operatorului new. Iniializare
| C# permite cteva forme de iniializare a tablourilor neregulate:
Partea I. L im bajul C# C apitolul 3. F undam entele lim bajului C# 41
40

1. Fie tabloul neregulat:


[ Accesarea elementelor
i n t[][] a = new i n t [ 3 ] []; Pentru un tablou neregulat ale crui elemente sunt tablouri unidimensionale,
[accesarea se face la fel ca la tablourile din C++: a[i] [j ] .
Elementele tabloului se pot iniializa cu sintaxa:

a[0] = new int[] {2, 7, 3, 8}; [Exemplu:


a[l] = new int[] {0, -1 };
a [2] = new int[] {1, 9, 4 }; jusing System;

Tabloul are ntradevr, form neregulat. Iclass JaggedArray

2 7 3 8 | static void Main()


a 1
0 -1 | int[] [] a =

1 9 4 | new int[] { 1, 4 },
1 new i n t [] { 5, 9, 0, 7, 2 },
2. A doua variant de iniializare a unui tablou neregulat este urmtoarea: | new int[] { 6, 8, 3 }
I };
in t[][] a = new i n t [ ] []
{ for (int i 0; i < a.Length; i++)
new int[] f 1, 4 },
new i n t [] { 5, 9, 0, 7, 2 }, for (xnt j 0/ j 'C aifij .Lsncffch ; j++)
new i n t [] { 6, 8, 3 } Console.Write(a[i][j] + " ");
}; Console .Writ'eLine () ;

3. A treia variant de iniializare este:


int[] [] a =
{
new i n t [] { 1, 4 }, I Ieire:
new i n t [] { 5, 9, 0, 7, 2 },
fl 4
new int[] {6 , 8 , 3 }
|5 9 0 7 2
};
|6 8 3
4. Cu ajutorul cuvntului cheie var, se pot iniializa att variabile simple ct j
tablouri cu tipuri implicite: \ Tablouri neregulate cu elemente de tip tablou multidimensional
var d = 3.5; // var nlocuiete double I Elementele unui jagged array pot fi tablouri multidimensionale.
var s = "Salut" // var nlocuiete string
1 1-
// Tablou unidimensional, var inlocuieste string]
I Exemplu:
var p = n e w [] { "C#", nuli, "C++", "Java" }; I Elementele tabloului neregulat a sunt tablouri dreptunghiulare de valori int:

// Tablou neregulat, var inlocuieste int[][] |int[] [, ]a = new int[3] [, ]


var q = new[]
{ n e w [] { 7 , 4 } , I new i n t [,] { {2, 9}, {4, 7}, {5, 0} },
n e w [] { 2, 0, -4, 8 } | new int[,] {(1, 5}, {3, 12} },
}; | new int[,] <{8, 6}, {2, 9}, {0, 6}, {3, -1} }

n fiecare caz compilatorul deduce tipul de dat din tipul constantelor de iniializai^
42 Partea I. L im bajul C# C apitolul 3. F undam entele lim bajului C# 43

Accesarea elementelor tabloului se face astfel: a[i] [j, k ] , unde i este al i-lea|
tablou din a, iar j i k este poziia valorii cutate n matricea i. De exem plu,! n cazul instruciunilor if imbricate, trebuie s inei seama de regula conform
valoarea -1 din a, se obine: a [2] [3, 1]. s creia un else se asociaz cu cel mai apropiat if care nu are else:

if (expresiei)
if (expresie2)
In stru c iu n i instruciunel;
else
n C# o declarare (statement) poate fi: o expresie, o instruciune simpl, oj| intruciune2; II se asociaz cu if (expresie2)
instruciune compus, o instruciune de control al fluxului de execuie (if, for,|
while, etc.), un apel de funcie, un bloc de cod, dar i o declarare de variabil! 0 e retinut:
local. | 1. Metoda ReadLineO din clasa System, c o n s o le citete linia
Un program C# este o secven de asemenea statements care se evalueaz| urmtoare din stream-ul standard de intrare {tastatur).
n ordine. n continuare, vom folosi cuvntul instruciune pentru statement. Fiecare;! 2. Metoda Parse(s), membr a structurii System.Int32 convertete
intruciune se termin cu Intruciunile C# sunt preluate cu unele mici modificri! stringul s ntr-un numr ntr-un nteg pe 32 de bii. Amintii-v c tipul
din C i C++. n continuare vom prezenta intruciunile care controleaz fluxul de ; int este un alias pentru structura Int32.
execuie al programului. j|
>! Din pcate biblioteca .N E T nu furnizeaz operatorul , aa cum o face
In s tru c iu
i n e a d e s e le c ie
if ... else f C++, capabil s extrag bytes din stream-uri i s-i converteasc direct spre tipul
Instruciunea i f . . . e l s e este mprumutat din limbajul C. Controleaz; dorit (Exemplu C++: int x ; cin x). Metodele Read() sau ReadLineO
fluxul programului prin evaluarea unei expresii booleane. n funcie de valoarea de I care se definesc ca membre ale diferitor clase din .N E T , citesc ntotdeauna din
adevr, selecteaz pentru executare o secven de instruciuni sau o alta. ; | stream-urile de intrare un caracter, un bloc de caractere sau o linie i returneaz
caracterul citit sau un string. Drept urmare, de cte ori avei nevoie -s citii valori
if (expresie_boolean) numerice, vei obine un string, pe care l vei converti cu Par se (). Toate tipurile
instruciuneal; de date ntregi Intl6, Int32, SByte, etc, definesc aceast metod.
else
instructiunea2; Instruciunea de selecie s w itc h
Instruciunile if imbricate sunt greu de scris corect, greu de citit i greu de
sau
depanat, switch este o intruciune de control mai potrivit atunci cnd avei un set
if {expresie_boolean) complex de alegeri de fcut. Sintaxa este identic cu cea din C++.
{
bloc instruciunii ; Sintaxa:
}
else jswitch ( )
{
bloc ir,struciuni2; : case vall: bloc_instruciunil;
} break;
case val2: bloc_instruciuni;
E xem plu: break;
// alte cazuri
string s = Con s o l e .R e a d L i n e O ; default: bloc instruciuni; // opional
;>
int x = i n t .P a r s e (s); n este o variabil de tip ntreg, de tip char sau de tip string. vall, val2, ... etc,
if ( x >= 0 ) sunt valorile pe care le poate lua n. Controlul este transferat etichetei case care
Console.Write("pozitiv") ; potrivete valorii lui n.
else Diferena fa de switch din C++ este aceea c C# nu suport cderea
Co n s o l e .Write("negativ"); implicit la seciunea urmtoare (fall through). Exemplul urmtor nu va compila:
44 Partea I. L im bajul C# C apitolul 3. F undam entele lim bajului C# 45

int k = 0;
switch ( k ) Sintaxa:
{
case 0: fo r e a ch (T i p i d e n t i f i c a t o r in e x p r e s i e )
Console.WriteLine ( "cazul 0" ); b lo c_instruciuni;
// goto case 1;
case 1: I Exemplu:
case 2:
Console.WriteLine( "cazul 1 si 2" ) using System;
break;
} class TestForeach
{
Cderea prin ramuri se poate face numai pentru cazuri vide, cum e case 1. Dac ; static void Main()
dorii un salt direct la o anume etichet, folosii instruciunea de salt necondiion, {
goto. Dac scoatei de sub comentariu goto case 1 ; n secvena de progra i n t [] a = {10, 20, 30)
precedent, atunci pe ecran se va afia: foreach (int x in a)
Console.Write(x
cazul Console.WriteLine()
cazul si 2
string[] st = { "UNU", "DOI", "TREI"
1! foreach (string s in st)
Ciclul f o r
Console.W r i t e (s + " ");
Este o instruciune identic cu cea din C++.
i
ll
Sintaxa:
I Ieire:
for (e x p r e s i e i ; e x p r e s ie 2 ; expresie3)
{ 110 20 30
blo c_ in stru ciu n i; iONU DOI T R E I
}
Ciclul w h i l e
Dac bloc_instruciuni e format din o singur instruciune, atunci acolade!
sunt opionale. Se evalueaz mai nti expresiei. Apoi se evalueaz : Este mprumutat fr modificri din C++.
expresie2. Aceasta controleaz bucla. Dac expresie2 este evaluat true, s
execut instruciunile cuprinse ntre acolade, apoi expresie3. Se reia evaluare i Sintaxa:
expresie2 i. ciclul continu pn cnd expresie2 este evaluat false. Api
iwhile ( e x p r e s i e )
controlul este cedat instruciunii urmtoare ciclului for.
!(
Toate expresiile sunt opionale. Dac expresie2 lipsete, condiia de tei
bloc_instruciuni;
este evaluat true:

fo r ( ;; )
|Dac bloc_instruciuni e format dintr-o o singur instruciune, atunci
Console.Write("Ciclu infinit!");
^acoladele sunt opionale. Se evalueaz expresie. Dac este evaluat true,
atunci se execut bloc_instruc:iuni. Se reia evaluarea expresiei. Ciclul
Ciclul f o r e a c h Icontinu ct timp este evaluat true.
foreach este nou n familia de limbaje C. Este folosit pentru iterarea prini
elementele unui tablou sau ale unei colecii. Coleciile sunt containere de t ^Exemplu:
generic, care pot reine secvene omogene de obiecte, aa cum vom vedea mi
trziu.
46 Partea I. L im bajul C#

int x = 5 ;
while ( x > O )
x-- ;

Ciclul d o w h ile
Este preluat fr modificri din C++. Este un ciclu cu test final, deci
bloc_instruciuni se evalueaz cel puin o dat.

Sintax:

do
{
b lo c _ in s tr u c iu n i;
} while (e x p r e s i e );

Dac bloc_instruciuni e format dintr-o o singur instruciune, atunci


acoladele sunt opionale. Se evalueaz bloc_instraciuni, dup ca re l
expresie. Ct timp aceasta se evalueaz trae, ciclul continu. n momentul ni
care expresie se evalueaz false, se transfer controlul intruciunii im ediat|
urmtoare ciclului.

Exemplu:

int x = 5;
do
{
x--;
} while ( x > 0);

Observaie
Rezultatul evalurii expresiilor care controleaz buclele C# trebuie s fie <j!
valoare boolean, adic true sau false. Secvena urmtoare nu va compila: [

int x = 5; j
do |
< j
x--; 1
} while ( x ); // Ilegal! x este evaluat la o valoare int |

Instruciuni
* de salt necondiionat
*
C# admite instruciunile de salt g oto, break i c o n tin u e . ij
Instruciunea g o t o ij
Utilizarea goto este nerecomandabil, deoarece produce cod greu da ;
neles (cod spaghetti). n cazul n care dorii totui s o folosii urmai paii: i:
!:
1. Creai o etichet ( identificator urmat de : ) t
2. g o to etichet
C apitolul 3. F undam entele lim baju lu i C# 47

kExemplu:
i
tusing System;
Ii
>public class GoTo
I {
f 3 tatic void Main)
[ {
! int x = 1;
\ repeta: li Eticheta
| Console.W r i t e ( x + " ");
x+ + ;
[ if (x <= 5)
l goto repeta; // Salt la eticheta
I >
I 1
[
I Ieire:
ijr1 2 3 4 5

t
i
i Instruciunile b r e a k i c o n t in u e
Dac n blocul de instruciuni al unei bucle se execut continue, atunci are
[ loc un salt la nceputul buclei. Instruciunea break duce la ieirea forat din ciclu.
; Exemplu:

; using System;

l public class TestBreakContinue


i t
static v o i d Main)
{
for (int i = 1; i <= 100; i++)
{
if (i % 2 == 1) // Pentru valori impare
continue; // salt la expresia i < 10
Console.Write(i + " );
if (i == 10) break; // "Rupe" bucla
}
}
}
Ieire:

o 2 4 6 8 10
48 Partea I. L im bajul C#

Sugestie i
Nu este indicat sutilizai intens aceste instruciuni,deoarece creeaz puncte j
multiple de ieire din cicluri, ceea ce duce la cod dificil de neles i de ntreinut j
(cod spaghetti). \

S p a ii de num e j
n capitolele 2 i 3 s-au discutat primele noiuni referitoare la s p a ii de num e j
(,namespaces). Am artat c sunt containere logice care gzduiesc definiii ale >
tipurilor de date. Au fost introduse n C# pentru evitarea conflictelor de nume n j
utilizarea bibliotecilor de clase, dar i pentru organizarea i sistematizarea tipurilor |
de date. De exemplu, dac ntr-o aplicaie utilizai dou biblioteci neprotejate prin I
spaii de nume, care provin de la furnizori diferii, este posibil ca un acelai nume t
de clas, s-i spunem Button, s fie definit n ambele biblioteci, ceea ce ar crea o :
coliziune n program, inacceptabil de ctre compilator. 1
ntreaga^ B ib lio te c a de Clase .NET se gsete n interiorul acestor j
namespaces. n afara spaiilor de nume ale bibliotecii .NET Framework sau ale j
bibliotecilor altor furnizori, C# v permite s v creai propriile spaii de nume. Se s
definesc foarte simplu cu ajutorul cuvntului cheie namespace. j
Exemplu: I
I
namespace MySpace j
< 1
static void Main() j
{ i
} 1
I
I
Spaii de nume imbricate (nested) \
ntr-un spaiu de nume putei defini nu numai tipuri de date ci i alte spaii de }
nume. j
Exemplu: j

namespace X
< j
namespace Y i
{ j
> I
namespace Z j
< I
namespace W j
{ I
>
}
static void Main()
j
{ !
} j
C apitolul 3. F undam entele lim bajului Cir 49

n interiorul lui x s-au definit alte dou spaii de nume Y i z i metoda M a in ( ) - n


Z s-a definit W.

Accesarea num elor de tipuri


Accesarea numelor definite ntr-un namespace se face preciznd toate
spaiile de nume pn la numele clasei dorite, separate ntre ele cu operatorul
punct ( . ) .

E xem plu:
Cum vom accesa numele clasei B u t t o n ?

System n figur s-a ilustrat faptul c spaiul de nume


System include spaiul de nume Windows,
Windows care la rndul lui include Forms. Clasa
Button, ca de altfel toate clasele de tip
Forms fereastr se definesc n Forms.
Cum accesm numele Button ? Vom
.clasa crea un obiect de tip Button astfel:
Button
System.Windows.Forms.Button b =
new System.Windows.F o r m s .B u t t o n ();

Cam complicat, nu-i aa ? Din fericire, exist


directiva using.

Figura 3.1 Accesarea numelor

Programele C# ncep de regul cu o seciune de directive using. ([4])


using precizeaz spaiile de nume cel mai utilizate n program. n felul acesta
programatorul nu mai este nevoit s scrie ntreaga cale (fully qualified name) pn
la clasa cutat.

a) Accesarea unui nume de clas folosind calificarea complet a numelui acesteia:

public class NestedNamespaces


<
s t a t i c v o i d Main()
{

System.Windows.F o r m s .Button b =
new System.W i n d o w s .F o rms.B u t t o n ();
}
}
50 P artea I. L im bajul C#

b) Accesarea unui nume de clas cu utilizarea directivei using:

using System.Windows.Forms;

public class NestedNamespaces


{
static void Main()
{
Button b = new B u t t o n ();
f
}

Not:
Pentru ca programul de lapunctul b) s compileze, trebuie s aducei
proiectului de tip consol o referin,la spaiul de nume System. Windows.Forms ^
astfel: I
n S o lu tio n E xp lo re r, click dreapta pe numele proiectului.
Alegei A dd reference.
n tab-sheet- u l .N e talegei System.Windows.Forms i apsai OK.

A T E N IE ! I
O directiv u sin g nu v permite accesul la nici un spaiu de nume definit n
spaiul de nume pe care l specificai.

Exem plu:

using System;

public class WrongAcces


{
static void Main()
t
W i n d o w s .F o r m s .Button b = new W indows.F o r m s .B u t t o n ();
}
}

Programul de mai sus nu compileaz, deoarece Windows este un spaiu de nume


imbricat n System i nu putei avea acces la acesta, ci doar la numele de tipuri |
(clase sau structuri ) din System. Cu directiva de mai sus, este corect s scriei |
astfel: I
i
!!
System.Windows.F o r m s .Button b = J
new System. Windows .Forms .Button () ; jj
1
ij
Alias-uri j|
Pentru simplificarea scrierii putei declara nume alternative pentru spaiile de j
nume, astfel: jj
C apitolul 3. F undam entele lim bajului CU 51

a) Introducerea unui alias pentru spaii imbricate, definite de programator:

using N = N1.N2.N3; // Creeaz un alias N

namespace N1
t
namespace N2
{
namespace N3
{
public class C { }
}
1
}

public class TestAlias


{
static void Main)
{
N.C ob = new N.C ();
>
}

b). Introducerea unui alias pentru spaii de nume predefinite:

using F = System.Windows.Forms;

public class TestAlias


{
static void Main()
{
F .ComboBox cb = new F .ComboBox();
}
}

Directive de p reprocesare

nainte ca programul s fie compilat, un alt program numit preprocesor,


ruleaz i pregtete programul pentru compilare. Preprocesorul detecteaz
directivele de preprocesare i stabilete nite reguli de compilare n raport cu
acestea. Directivele ncep cu caracterul #. Le vei introduce n situaii n care dorii
ca unele poriuni de cod s nu fie compilate n anumite condiii. De exemplu, n
etapa de b u ild fin a l a unei aplicaii, nu dorii s mai compilai poriuni de cod pe
care l-ai folosit pentru depanare.
52 P artea I. L im bajul C#

Directiva # d e fin e
Numele simbolice se definesc cu directiva #define, naintea oricrei
secvene de cod din program. Alte directive pot fi definite i n alte zone ale
programului.

Exemplu:

#define DEPANARE
// Cod neafectat de directiva #define
#if DEPANARE
// Cod care se compileaz dac este definit numele DEPANARE
#else
// Cod care se compileaz daca nu este definit DEPANARE
#endif f
II Cod neafectat de preprocesor

Cnd preprocesorul ruleaz, el caut directiva #defne. Dac aceasta exist, ia


not de identificatorul d e p a n a r e . Directiva #if testeaz existena identificatorului
n funcie de aceasta, seteaz pentru compilare o poriune de cod sau alta.
Orice cod care nu este cuprins ntre #if i #endif este compilat de ctre
compilator.

Directiva # u n d e fin e
Dac ntr-un punct n program dorii ca un anume identificator definit cu
#define s nu mai fie definit, deci s nu mai fie cunoscut de ctre preprocesor,
atunci folosii directiva #undef:

#define DEPANARE
#define MAXIM

// Cod neafectat de directiva #define


#if DEPANARE
// Cod care se compileaz
#endif

#undef DEPANARE

#if DEPANARE
// Cod care NU se compileaz
#elif MAXIM
// Cod care compileaz pentru c nu e definit DEPANARE,
// dar este definit MAXIM
#endif

S observm c #elif testeaz existena unui nume simbolic doar n cazul n


care testul #if eueaz.
C apitolul 3. F u ndam en tele lim bajului CU 53

R ezu m atul capitolulu i

Tipurile predefinite din C# (int, char, string), sunt mapate direct


peste tipuri struct din spaiul de nume System. De exemplu, tipului int
i corespunde clasa System. Int32 din Biblioteca de Clase .NET.
Tipurile definite cu ajutorul cuvintelor cheie class sau struct se
numesc tipuri definite de programator.
Variabilele de tip clas se numesc obiecte sau instane ale clasei.
Tipurile valoare sunt toate tipurile predefinite (char, int, float, etc.),
cu excepia tipurilor string i object.
Tipurile referin, se definesc de ctre programator. n aceast categorie
se includ tipurile clas, tipurile interfa, tipurile delegat i tipurile array
(tablourile).
Datele variabilelelor de tip valoare, se memoreaz pe stiv (Stack).
n cazul tipurilor referin, referinele sunt n stiv, iar datele se aloc
dinamic n Heap.
n C# tablourile sunt tipuri referin. Tablourile pot fi unidimensionale
sau multidimensionale. Cele multidimensionale, ia rndul lor pot fi
dreptunghiulare sau neregulate (jagged ).
Instruciunile de control al fluxului de execuie a programului (if, for,
while, etc) sunt similare sintactic cu cele din limbajul C++.
ntreaga Biblioteca de Clase .NET se gsete n interiorul spaiilor de
nume. n afara spaiilor denume predefinite, programatorii pot s
defineasc propriile spaii de nume cu ajutorul cuvntului cheie
namespace.
Directivele de preprocesare se introduc n situaiile n care se dorete ca
unele poriuni de cod s nu fie compilate n anumite condiii.

n trebri i exerciii

1. Care este diferena dintre tipurile valoare i tipurile referin ?

2. n ce condiii se produc erori la compilare atunci cnd declarai o variabil?


Dar o constant ?

3. n care zone ale memoriei RAM se memoreaz membrii unei clase ?

4. Declarai i iniializai un tablou bidimensional dreptunghiular cu 4 linii i 3


coloane.

5. Declarai i iniializai un tablou bidimensional neregulat cu 3 linii.

6. Definii dou spaii de nume: X i Y, unde Y este coninut n X. n Y definii


clasa A. Scriei dou programe C# n care se instaniaz clasa A, utiliznd
moduri diferite de accesare a numelui clasei.
54 P artea I. L im bajul C#

C apitolul 4

Programare Orientat pe Obiecte n C#


P rogram area O rientat pe O biecte (OOP) este cea mai influent
paradigm de programare a timpurilor noastre. Prin paradigm" se nelege stil de
programare. n raport cu stilul de programare procedural, OOP reprezint o cu
totul alt abordare a programrii.
n limbajulele C sau Pascal ca i n toate celelalte limbaje procedurale, se
pot defini tipuri de date i n mod separat funcii care acioneaz asupra acestora.
Separarea tipurilor de date de funciile corespunztoare, impune programatorului
eforturi considerabile pentru a menine logica gruprii acestora, mai ales cnd :
aplicaia are mii de linii de cod.
n OOP funciile sunt grupate n acelai obiect, mpreun cu datele asupra '
crora opereaz. Datele sunt mai complexe n OOP i mai bine organizate. I
Organizarea superioar se dovedete foarte util atunci cnd se scriu aplicaii i
foarte mari, cnd se lucreaz n echip i cnd se scrie cod pentru biblioteci care ]
vor fi folosite de clieni. i

O biecte i clase \
i
j
Limbajul C# este un limbaj orientat-obiect. Limbajele orientate pe obiecte au .j
calitatea c permit programatorului s-i creeze noi tipuri complexe de date. ;i
Tipurile se obin prin definirea de clase. Clasele sunt baza programrii orientat pe j
obiecte. O clas reunete cod i date care descriu o anumit categorie de obiecte. \
Clasa este apoi folosit pentru construirea de obiecte. Crearea unui obiect se j
numete in sta n ie re . Obiectul creat se numete in sta n a clasei.
Diferena dintre un obiect i o clas este aceeai ca diferena ntre o pisic i t
descrierea unei pisici. Descrierea este clasa, iar pisica este obiectul. De altfel,
clasele i obiectele au aprut n programare tocmai din necesitatea de a modela j;
obiectele din realitate, dar i obiecte abstracte. !
O clas Pisica, specific trsturile care ne intereseaz ia o pisic: nume, |
ras, greutate, culoarea blnii, etc. De asemenea, clasa descrie aciunile pe care o 1
pisic le poate face: s sar, s zgrie, s toarc, etc. Pisica Kitty, rasa Birmanez, j
greutatea - 4 Kg, culoarea blnii - gri, este o instan a clasei, deci un obiect de tip j
Pisica.
Marele avantaj al claselor este c ncapsuleaz caracteristicile i
capabilitile obiectului ntr-o singur unitate de cod. O clas descrie complet
obiectele de tipul su, nemaifiind nevoie n acest scop de cod exterior clasei.
Mai trebuie s reinei urmtoarele: programarea orientat pe obiecte nu ;
este doar programare cu obiecte. ntre obiecte pot exista relaii, obiectele pot ;
comunica ntre ele, obiectele pot folosi alte obiecte. j
Capitolul 4. Program are O rientat pe O biecte n C# 55

M ecanism ele fundam entale ale OOP

Toate limbajele orientate pe obiecte au cteva caracteristici comune:

1. Abstractizarea
Abstractizarea este simplificarea realitii prin modelarea unor clase care
pstreaz doar trsturile obiectului real care sunt eseniale i suficiente pentru
atingerea scopului propus. Membrii clasei (cmpuri, metode, etc.) definesc aceste
trsturi.

2. ncapsularea
Un obiect ncapsuleaz date i cod care acioneaz asupra acestor date.
Clasa ofer protecie membrilor si. Nu toi membrii clasei pot fi accesai din afara
ei. O regul important n OOP este aceea c datele membre trebuie s rmn
private, s fie inaccesibile din lumea exterioar clasei, pentru a prentmpina
modificrile accidentale. Partea accesibil a clasei o constituie membrii publici, de
regul metodele. Acetia pot fi utilizai de ctre poriuni din program care lucreaz
cu obiectele clasei. Membrii publici ai unei clase formeaz in te rfa a clasei.

3. Motenirea
Motenirea este mecanismul prin care un limbaj orientat-obiect v permite s
definii noi clase care incorporeaz i extind o clas deja definit. Noile clase se
numesc clase derivate. Ele motenesc atributele i comportamentul clasei pe care
o extind, fiind versiuni specializate ale clasei de baz. Clasa pe care o extindei se
numete clas de baz. Ca exemplu, s presupunem c dorii pentru aplicaia
dumneavoastr un buton care s aib funcionalitatea unui buton de apsare, dar
s aib n plus anumite proprieti: s fie rotund, s aib un mic punct luminos
central care clipete cnd este apsat, etc. Avei dou opiuni: s scriei o clas
care s ndeplineasc toate cerinele sau s scriei o clas MyButton, care s
moteneasc de pild clasa System.Windows .Forms .Button. A doua variant
este avantajoas, deoarece clasa MyButon motenete ntregul comportament i
caracteristicile unui buton obinuit i vei avea nevoie s adugai doar codul cerut
de cerinele suplimentare. R e u tiliz a re a c o d u lu i este unul dintre beneficiile
importante pe care le aduce motenirea.

4. Polimorfismul
n programarea orientat pe obiecte, polimorfismul (cuvnt care vine din
greac i care nsemn a avea mai multe forme") este caracteristica unei interfee
de a fi folosit cu aciuni multiple. O funcie sau un obiect au un comportament
polimorfic, dac acestea au mai mult de o singur form.
Polimorfismul, caracterizat de expresia interfa comun, aciuni multiple",
este deci capacitatea de a folosi n funcie de context, mai multe forme ale unui tip
sau metod, fr s ne intereseze detaliile de implementare.
Exist cteva tipuri de polimorfism. Unul dintre acestea se obine n OOP cu
ajutorul motenirii. S lum un exemplu din viaa real: Un dresor de circ are trei
animale : un arpe, un porumbel, i un tigru. Cnd vrea s cheme unul dintre ele,
i 56 Partea I. L im bajul C#

le trimite un unic m e s a j: la m asa f . Ca rspuns la acest mesaj, arpele se


trte, porumbelul zboar, iar tigrul alearg. S ne imaginm clasele arpe,
Porumbel i Tigru. Toate clasele motenesc clasa Animal. Fiecare clas i-a
definit aceeai interfa, metoda LaMasa, dar cu aciuni diferite. Obiecte diferite
(animalele) rspund n mod diferit aceluiai mesaj (metoda LaMasa ()). Pentru f j
dresor nu este important cum procedeaz fiecare animal pentru a veni (detaliile de
implementare ale metodei LaMasaQ ), ci conteaz doar faptul c animalul vine la
mas.

Clasele C#

n afara celor cincisprezece tipuri predefinite n C#, putei crea propriile tipuri i
de date (user-defined types). Exist ase categorii de tipuri pe care le putei crea:

1. Tipuri c la s s
2. Tipuri s tr u c t
3. Tipuri ta b lo u
4. Tipuri enum
5. Tipuri d e le g a te
6. Tipuri in te rfa c e

Odat ce ai definit un tip de dat l putei utiliza ca i cnd ar fi un tip prdfinit. 1


Dintre tipurile enumerate mai sus, c la s s este cel mai important. O clas
este o structur de date care poate depozita date i executa c o d . Primele noiuni |
despre clasele C# au fost discutate n capitolul 3.

Definiie
Clasele sunt entiti logice care modeleaz obiecte din lumea real sau
obiecte abstracte. Clasele ncapsuleaz date i fu n c ii care opereaz cu aceste;
date. }

C a ra c te ris itic ile obiectului se memoreaz n c m p u rile clasei.


C a p a b ilit ile , aciunile obiectului, se codific n m e to d e le clasei.

C m p u r ile (acestea sunt date m em bre) sunt v a ria b ile care reinl
informaii despre obiect.
M e to d e le sunt fu n c ii m e m b re ale clasei.

Cmpurile i metodele unei clase se numesc m e m b rii c la s e i. O clas poate avea)


un numr orict mare de date membre i de funcii membre. Membrii pot fi oricare |
combinaie a urmtoarelor tipuri de membri: |[
Jj
D ate m e m b re F u n c ii m e m b re
C m p u ri M e to d e
* C o n s ta n te * P ro p rie t i
C o n s tru c to ri
C apitolul 4. P rogram are O rientat pe O biecte n C# 57

D e s tru c to ri
* O p e ra to ri
In d e x a to ri
> E v e n im e n te

Definirea c la s e lo r
0 clas se declar cu ajutorul cuvntului cheie class.

Sintaxa minimal:
class nume_clas
{
// Cmpuri
[modificator de acces] Tip nume;

// Metode
[modificator de acces] TipRetur NumeMetod(Parametri);
}

Modificatorii de acces controleaz regiunile programului care pot accesa membrii


clasei. Tabelul descrie cele ase tipuri de modificatori:

A trib u tu l D e s c rie re
public Acces nelimitat
private Acces limitat la propria clas
protected Acces limitat la propria clas i la clasele derivate
internal Acces limitat la programul care conine clasa
protected internal Acces limitat la program i la clasele derivate

Dac modificatorul de acces lipsete, atunci membrul respectiv este n mod implicit
private. Parantezele ptrate indic opionalitatea.

Cum se lucreaz cu obiecte ?

1. Mai nti se definete clasa. E x e m p lu :

class X
(
// membrii clasei
}

2. Acum putei utiliza tipul x pentru a crea obiecte:

X r = new X () ;

r este referin la obiectul de tip X care se aloc dinamic cu new X() n


(Heap-ul sistemului). x ( ) este constructorul clasei X.
58 P artea I. L im bajul C#

Despre constructori vom discuta ntr-unul dintre paragrafele urmtoare.

3. Folosii referina pentru a accesa membrii clasei:

r.membru; // Cu operatorul . se acceseaz membrii clasei

Exemplul 1:

class Program i

{ static void Main() 1;


{
}
}

Clasa Program are ca membru doar metoda static Main(). Aceast metod
este punctul de intrare n program (entry point). Membrii statici ai unei clase exist
independent de obiectele clasei. Din acest motiv, Main () poate fi apelat de ctre
platforma .NET, fr s fie nevoie de un obiect de tip Program.
I
Exemplul 2:

class Test I
{
int x = 100; // Cmp privat

static void Main()


{
// x = 10; // Greit! x trebuie s aparin
// unui obiect
Test r; // Declar o referin
r = new T e s t (); // Creaz un obiect
r.x = 20; // Corect, x este privat, dar
} // M a i n () e membr a clasei
}

Exemplul 3:

using System;

class Test
f
private int x; // Cmp privat

// Metode publice
public int GetX()
{
return x;
}
Capitolul 4. P rogram are O rientat pe O biecte n C# 59

public void SetX(int n)


{
x = n; // Metodele clasei au acces
} // la cmpurile private
}
class Program
{
static void Main()
{
Test r; // Declar o referin
r = new Test() ; // Creeaz un obiect
r.x = 20; // Greit. x este private
r.SetX(lO); // C o r e c t . SetX() este public
Console.WriteLine(r..G e t X ()) ,
}
}

Ieire: 10
Programul de mai sus are dou clase. n clasa P r o g r a m , metoda M a i n ( ) ,
I creaz un obiect de tip T e s t , care mai apoi este utilizat pentru accesarea
I membrilor si publici,
i
f
| Metode. Parametrii metodelor.
t

I Metoda este un bloc de cod care poate fi apelat din diferite pri ale
| programului i chiar din alte programe. Cnd o metod este apelat, i execut
codul, apoi transfer controlul codului care a apelat-o. Metodele pot fi
implementate ca membri ai claselor sau ai structurilor sau ca prototipuri n interfee.
| Metodele pot s aib sau s nu aib parametri i pot s returneze sau nu valori.
| Dac nu returneaz valori, returneaz void. De asemenea, metodele pot fi s ta tice
| sau ne-statice.

I A TE N IE !
I Spre deosebire de C sau C++, n C# nu exist metode globale. Metodele nu
se pot declara n afara unui tip de date.

\f Sintaxa minimal a unei metode este:

j [M o d i f i c a t o r A c c e s ] T ip R e tu r N u m e M e to d (L ista P a ram etri)

// codul metodei
| 1

Apelul unei metode:

NumeMetod (Li sta Argumente) ;


A rgum entele (sau parametrii actuali) sunt valorile sau obiectele cu care se
apeleaz metodele.
60 Partea I. L im bajul C #

Parametrii unei metode pot fi precedai n C# de cteva cuvinte cheie, numite


modificatori. Modificatorii sunt: ref, out, params. Acetia controleaz modul n
care argumentele sunt transmise unei metode.

Parametri valoare
n mod implicit, tipurile valoare sunt pasate metodelor p rin valoare. Aceasta
nseamn c atunci cnd un obiect de tip valoare este transmis ca argument unei
metode, o copie temporar a obiectului este creat de ctre metod pe stiv. Cnd
metoda i termin execuia, copiile temporare sunt distruse. n general avei
nevoie doar de valoarea argumentelor, ns sunt situaii cnd dorii s modificai
valoarea argumentelor. n acest caz, mecanismul transmiterii prin valoare nu v
ajut.
Exem plu:

using System;

class S
{
public void Schimba(int x, int y) // x, y - parametri
{ // formali
int aux; // x, y, aux - variabile locale
aux = x; x = y; y = aux;
)
}

class Test
{
static void Main()
{
S s = new S ();
int a = 10, b = 20; // a, b - variabile locale
*
/ / a , b - argumente pasate prin valoare ||
s.Schimbata, b ) ;
Console.WriteLine("a = {0}, b = {1}", a, b) ;

Programul afieaz: a = 1 0 , b = 20
Observm c a i b au rmas nemodificai n urma apelului, deoarece la 1
transmiterea prin valoare x i y sunt copii locale ale argum entelor a i b. |f
Argumentele nu trebuie s fie n mod obligatoriu variabile. Poate fi argument orice 1|
expresie care se evalueaz la tipul parametrului formal. jj

Parametri referin j
Dorim s modificm programul anterior, astfel nct valorile a i b s se jj
modifice dup apel. Se aplic modificatorul re f asupra parametrilor formali
j:
asupra parametrilor actuali astfel:
C apitolul 4. P rogram are O rientat pe O biecte n C# 61

public void Schimba(ref int x, ref int y)


{
int aux;
aux = x; x = y; y = aux;
>

int a = 10, b = 20; // Iniializare obligatorie


s .Schimba(ref a, ref b ) ; // Apel
//s.Schimba(2*a, b - 1); // Greit! Argumentele nu
// sunt variabile de memorie
Rulai programul. Va afia: a = 20, b = 10

Cnd dorim s pasm argumente prin referin, atunci:


> Trebuie utilizat modificatorul ref att Tn definiie, ct i n apelul metodei.
> Este obligatoriu ca argumentul transmis funciei s fie o variabil, iar
acestei variabile trebuie s-i fie atribuit o valoare nainte de a fi utilizat ca
parametru actual.

Parametrii referin au urmtoarele caracteristici:


Nu aloc memorie pe stiva programului pentru parametrii formali.
Parametrul formal este de fapt un alt nume (un alias) pentru variabila de apel,
referind aceeai zon de memorie. Din aceast cauz, orice modificare asupra
valorii parametrului formal n timpul execuiei metodei, se exercit direct
asupra parametrului actual i persist dup apelul metodei.

Parametri de ieire
Parametri de ieire sunt utilizai pentru a transmite date din interiorul metodei
spre codul care a apelat-o. Nu conteaz valorile iniiale ale argumentelor, ci doar
cele finale.

Cerine:
> Trebuie utilizat modificatorul o u t att n definiie, ct i n apelul metodei.
> Este obligatoriu caargumentul transmis funciei trebuie sfie o variabil i
nu o expresie. Acestei variabile nu este nevoie s-i fie atribuit o valoare
nainte de a fi utilizat ca parametru actual.

Exemplu:

class OutP a r a m
{
public void Metoda(out int x)
{
// int y = x; // Eroare!
x = 100; // Iniializare nainte de
x++; // a se citi din variabila x
}
1
?
f

62 Partea I. L im bajul C#

class Program
{
static void Main(string[] args)
{
OutParam op = new OutParam) ;
int z; // Nu e nevoie de iniializare
op.Metoda(out z ) ;
System.Console.Write(z) ;
}
}

La fel ca n cazul parametrilor referin, parametrii de ieire (output parameters)


sunt a//'as-uri pentru parametrii actuali. Orice schimbare asupra unui parametru de [
ieire, se produce de fapt asupra argumentului funciei.

P a ra m e trii d e ie ire au urmtoarele c a ra c te ris tic i:


n interiorul metodei, parametrilor de ieire trebuie s li se atribuie valorii
nainte de a se utiliza valoarea acestora. Din acest motiv, valorile iniiale
ale parametrilor actuali (argumente) sunt nenecesare i nici nu este nevoie
s iniializai argumentele nainte de apelul metodei. jjB
Tuturor parametrilor de ieire trebuie s le fie atribuie valori nainte de*
revenirea din apel. I

Parametri tablou j
Parametrii tablou (parameter array) admit zero sau mai muli parametrii
actuali pentru un acelai parametru formal. I

R e s tric ii:
Poate exista doar un singur parametru tablou n lista de parametri
formali.
Dac exist un parametru tablou, atunci acesta este ultimul n lista'
de parametri formali.
Pretinde modificatorul params n declaraie, dar nu este permis n
apelul metodei.

Parametrii tablou se declar ncadrnd tipul parametrului la stnga cu modificatorul


params, iar la dreapta cu operatorul de indexare: [ ] .

E x e m p lu :

class Params
{
public void Prin(params int[] x)
{
foreach (int i in x)
System.Console.W r i t e (i + " ");
System.Console.WriteLine() ;
Capitolul 4. P rogram are O rientat pe O biecte n C# 63

class Program
{
static void M a i n (string[] arg3)
{
Params p = new Params <);
p . P rint(1, 3); // n
p.Pr i n t (2, 4, 6, 8);
int{] a = { 10, 20, 30 };
// n
}
p .Print(a); // n
}

Ieire:
1 3
2 4 6 8
10 20 30

Invocarea metodei se poate face n dou moduri: o lista separat prin virgul cu
valori de tipul parametrului (*), sau un tablou de elemente (**).
O ultim observaie: n C# tablourile sunt tipuri referin, astfel nct
parametrii tablou sunt i ei referine.

S u p ran crcarea m e to d e lo r

C# suport suprancrcarea metodelor clasei (o v e rlo a d in g ). Este vorba


depre procedeul prin care definii dou sau mai multe metode cu acelai nume, n
aceeai clas. Suprancrcarea are i restricii: metodele trebuie s difere prin
numrul i/sau tipul parametrilor formali.

Exemplu:
n clasa Overloading dorim s suprancrcm metoda: void F(int a) {}

class Overloading
{
void F(int a) { }
void F(char b) { } // Corect
void F(int a, char b) { } // Corect
void F(int a, int b) { } // Corect

// int F (int a ) {} // Greit! Tipul, parametrului


} // formal este acelai
Partea I. L im bajul C# Capitolul 4. Program are O rientat pe O biecte n C#
64 65 ,>
Observaie:
Membrii statici ai unei clase C# admite iniializarea datelor membre, la momentul declarrii lor, aa ca ~
mai sus: int y = 20; sau int x = 10;
n mod implicit, metodele i cmpurile clasei sunt ne-statice. Pentru a putea
Exemplul 2:
invoca o metod ne-static, avei nevoie de un obiect de tipul clasei. Metodele'
statice se pot apela n lipsa obiectelor. Ele au comportamentul unor funcii globalej Cnd accesai membrii statici din afara clasei trebuie s folosii sintaxa:
NumeClas.MembruSttic;
care ns nu sunt vizibile dect n cadrul clasei. De asemenea, cmpurile declarate*
s t a t i c , se aloc n memorie i pot fi folosite, chiar dac nu ai construit nici un,
class ClasaMea
obiect.
{
public static string s = "Ionel";
Accesarea membrilor statici. public static void F() { }
Fie clasa:

class C class Test


{ {
public static int x; static void Main(string[] args)
public static void F() {} {
} // s = "Marcel"; // Greit
ClasaMea.s = "Marcel"; // Corect
Accesarea acestor membri se face prin numele clasei, astfel: c . x i C.F() ; // F (); // Greit
E x e m p lu l 1: ClasaMea.F ( ) ; // Corect
}
class Program
{
static int x = 10;
static void F()
Constante
{
} Dac dorii s pstrai valori care nu se vor schimba pe parcursul execuiei
int y = 20; // Membri ne-statici programului i n acest scop vrei s le protejai la scriere, vei declara constante. n
void G() C# , constantele apar n dou forme:
{
} 1. C o n s ta n te lo c a le .
static void Main(string[] args) 2. C onstante m em bre ale clasei.
{
// Membrii statici aparin clasei Att constantele membre, ct i cele locale, se introduc cu cuvntul cheie c o n s t.
x = 100; // Corect C o n s ta n te le lo c a le .s e declar n corpul metodelor i sunt vizibile doar n corpul
F () ; // Corect acestora:

Program.x = 100; // Corect! Accesare prin void Metoda(int a)


Program.F(); // numele clasei. {
const int x = 100; // iniializare obligatorie
// Membrii ne-statici aparin obiectelor // x++ //Eroare!
// y = 200; // Greit 3. x ; // Corect
// G (); // Greit }
Program p = new Program();
p.y = 100; // Corect Constantele m em bre se comport la fel ca valorile statice. Sunt vizibile n fiecare
p.G() ; // Corect instan (obiect) al clasei i sunt disponibile chiar n lipsa obiectelor clasei.
} Exem plu:
66 P artea I. L im bajul C#

using System;

class C
{
public const int H = 24;
}

class TestConst
{
static void Main(string[] args)
{
Console.Write(C.H);
}
}

De reinut:
Constantele trebuie iniializate la declarare.
Constantele membre se acceseaz la fel ca membrii s ta tic i:
NumeClas.NumeConstant.

Constructori

C o n s tru c to ru l de in s ta n este o m etod special a clasei, care are rolul d j


a creea, a construi obiecte. O clas are cel puin un constructor. De fiecare dat j
cnd instaniai un obiect de tip s t r u c t sau c la s s , se apeleaz constructon, :
clasei.
Exemplu:

class Maina
{
public string marca; ,
public int pret;
} !

class Test
{
static void Main(string[] args)
{
Maina m = new Masina(); // Apelul constructorului '
}
}

Observai c instanierea obiectului presupune de fapt apelul constructorului clas


M a in a O - Toate clasele au un constructor. Putei defini proprii constructori,
cazul n care nu o facei, compilatorul va genera un constructor n mod implic
Clasa M a in a nu definete un constructor. n aceast situaie, compilatoi
genereaz un c o n s tru c to r im p lic it, fr parametri, M a in a ( ) , care construie
obiectul, dar nu intreprinde alt aciune.
C apitolul 4. Program are O rientat pe O biecte n C # 67

C o n stru cto ru l im p lic it iniializeaz cmpurile clasei cu urmtoarele valori


implicite:
Tipurile numerice (int, short, etc.) i tipul enum cu valoarea 0.
Tipul bool cu valoarea false.
Tipul char cu ' \ 0 ' .
i * Tipurile referin (inclusiv string sau tablouri) cu nuli.
I n mod frecvent vei dori s stabilii starea iniial a obiectului prin setarea unor
j valori iniiale ale datelor membre. Pentru aceasta, vei defini unul sau mai muli
constructori. De exemplu, pentru clasa Maina, putei scrie:

using System;

class Maina
! t
public string marca;
; public int pret;
l public Maina(string m, int p) // Constructor
I <
marca = m;
i pret = p;
\ >
I i

class Test

static void. Main (string [] args)


I (
// Maina m = new M a i n a (); // Greit! Nu mai exist
// constructorul implicit!
// Se invoc constructorul Maina(string, int)
Maina m = new Maina("Audi", 50000);
Console.W r ite (m.marca + " " + m.pret);
}

Ieire: Audi 50000


ATENTIE
t !
i In momentul n care ai definit cel puin un constructor, compilatorul nu mai
sintetizeaz constructorul implicit. De aceea, dac dorii i unul fr parametri,
f trebuie s-l definii.

Exemplu:
.
f class Maina
| (
i public string marca;
: public int pret;
68 Partea I. L im bajul C#

public M a i n a () // 1

marca = "Fiat";
pret = 1000;

public Maina(string m) // 2

marca = m;
pret = 20000;

public Maina(int p) //3

marca = "Ford";
pret = p;

public Maina(string m, int p) // 4

marca = m;
pret = p;
1
}

Acum putei crea obiecte de tip Maina n mai multe moduri: .

Maina ml = new M a i n a (); // constructor 1


Maina m2 = new M a i n a ("Opel"); // constructor 2
Maina m3 = new M a i n a (2000); // constructor 3
Maina m4 = new M a i n a ("Renault", 15000); // constructor 4

Caracteristicile metodelor constructor


II
Sunt metode care se apeleaz ori de cte ori, un obiect este creat.
Au acelai nume ca cel al clasei.
Nu au tip de retur, deci nu returneaz nimic, nici mcar void.
Pot fi suprancrcai, la fel ca oricare metod a clasei.
Pot s fie declarai static, pentru iniializarea membrilor statici ai clasei.
De regul se declar public, ns dac dorii ca un anumit constructor s
nu poat fi invocat din afara clasei, l declarai private. Procedai n
acest fel, mai aies cnd o clas conine numai membri statici. n aceast
situaie este inutil s permitei crearea de instane ale clasei (obiecte).

Constructori de copiere
Dac dorii ca un obiect s fie creat ca o copie fidel a unui alt obiect, atunc
este convenabil s definii un constructor de copiere (copy constructor). C# ni
furnizeaz un constructor de copiere implicit, aa cum ofer un constructor de
instan implicit. De aceea va trebui s-l definii dumneavoastr.
Exemplu:
C apitolul 4. Program are O rientat pe O biecte n C# 69

using System;

c la s s C
{
private int x; // Cmp privat

public C(int a) // Constructor de instan


{
x = a;
}
public C(C ob) // Constructor de copiere
{
x = o b .x ;
}
public int GetX() { return x; } // Metod accesor
}

class TestCopyCtor
{
static void Main(string[] args)

C cl = new C(10); // Apeleaza C(int)


C c2 = new Ccl); // Apeleaza C(C)
Console.WriteLine(c2.G e t X ()); // Afieaz; 10
>
}

Din exemplu vedem c parametrul constructorului de copiere are tipul clasei, iar
argumentul de apel este un obiect ( c l) al clasei.

Cuvntul cheie t h i s
this este o referin la obiectul curent. Toate metodele nestatice ale clasei
posed aceast referin i au acces la ea.
Exemplificm utilizarea referinei this n urmtoarele circumstane:
1. Pentru rezolvarea ambiguitilor care apar cnd numele parametrilor
formali ai unei metode coincid cu numele altor membri.
2. Returnarea de ctre o metod a unei referine la obiectul curent.

using System;

class Copil
{
private string nume;
private int varsta;
70 P artea I. L im bajul C#

// Parametrii formali au aceleai nume cu ale cmpurilor


public C o p i l (string nume, int varsta)
{
this.nume = nume; // cazul 1
this.varsta = varsta; // cazul 1
}
public Copil ModificVarsta(int varsta)
{
this.varsta = varsta; //cazul 1
r e t u m this; // cazul 2
}
public void A f i s e a z a O
I
Console.WriteLine(nume + " " + varsta);
}
}

class Test_this
{
static void Main(string[] args)
{
Copil c = nex Copil("Alin", 17);
c.Afiseaza(); // Ieire: Alin 17
c.ModificVarsta(l);
c.Afiseaza(); // Ieire: Alin 18
)
>

Ce s-ar fi ntmplat dac constructorul clasei s-ar fi definit a s tfe l:

public Copil (string nume, int varsta)


{
nume = nume;
varsta = varsta;
}

Nu este eroare la compilare. Dar parametrul formal nume ascunde cmpul clasei]
astfel nct metoda nu acceseaz cmpul privat al clasei, ci realizeaz o inutil
autoatribuire a parametrului formal. Oricare membru al clasei poate fi accesat ri
metodele clasei astfel: this .membru. n acest fel, this.nume = nume
realizeaz o iniializare corect a cmpului nume.
Mai observm c metoda M odificVarstaO returneaz o referin ti
obiectul curent. Cine este de fapt obiectul curent ? Asta nu vom ti, pn r
momentul n care metoda este apelat: c.ModificVarsta(18); Prin urmare,
refer obiectul curent i this refer evident acelai obiect. De altfel, n momenti
apelului, this refer deja obiectul alocat cu new, pentru c c transfer n thi
referina ctre obiect.
Exist i alte situaii n care avei nevoie de t h i s , aa cum vom vedea m<
departe.
Capitolul 4. P rogram are O rientat pe O biecte n C# 71

Destructorul clasei

Destructorul clasei este o metod special care distruge instanele claselor.


Dac o clas poate avea mai muli constructori, n schimb nu poate avea dect un
singur destructor. Un destructor se declar astfel:

cl a s s A v i o n
{
// Membrii clasei
~Av i o n ( ) // D e s t r u c t o r
{
// Eliberarea resurselor gestionate de obiect
}
}

n majoritatea covritoare a cazurilor, nu vei avea de implementat un destructor,


deoareace C# are un garbage co lle ctor care distruge obiectele nefolositoare n
mod automat. Vei implementa un destructor doar n situaii n care obiectele
gestioneaz resurse care nu sunt controlate de .NETFramework.
Nu vom intra n alte detalii care ies din cadrul propus n aceast lucrare.
Este bine s reinei totui cteva informaii utile n legtur cu destructorii:

IMPORTANT
Destructorii au acelai nume cu cel al clasei, prefixat cu caracterul ~.
O clas poate avea un singur destructor.
Destructorii nu se apeleaz niciodat. Ei se invoc n mod automat.
Constructorii nu au parametri i nu accept modificatori.
n structuri nu se pot defini destructori.
Destructori nu pot fi suprancrcai.

Proprieti

Proprietile reprezint o facilitate important a limbajului C#. Sunt membri


ai clasei care permit accesul direct la starea obiectului. Starea unui obiect este
dat de valorile datelor membre. Cu ajutorul proprietilor vei accesa cmpurile
private, ca i cnd ar fi fost declarate public, fr ca prin aceasta s se ncalce
principiul proteciei datelor, care cere ca datele membre s fie private. n realitate,
proprietile implementeaz nite metode speciale, numite accesori.
Exemplu:

using System;

clas3 C o p i l
{
private s t r i n g nume; // Cmpuri private
private int varsta;
72 P artea I. L im bajul C#

public Copil(string n, int v) // Constructor


{
nume = n;
varsta = v;
}

public string Nume // Proprietatea Nume


{
get
{
return nume;
}
set 1
{
nume = value;
>
}

public int Varsta // Proprietatea Varsta


{
get
{
return varsta;
>
set
{
varsta = value;
}
>
}

class TestProprietati
{
static void Main(string[] args)
{
Copil c = new Copil("Valentin , 18);
Console.WriteLine(c.Nume + " " + c.Varsta); // get
c.Nume = "Andrei"; // set
c.Varsta = 20; // set
Console.WriteLine(c.Nume + " " + c.Varsta); // get
}
)

Fiecare proprietate returneaz i eventual seteaz i valoarea unui cmp privat. S-


au implementat dou proprieti: Nume i varsta. Toate proprietile au tip.
C apitolul 4. P rogram are O rientat pe O biecte n C# 73

Prototipul proprietii este format din tipul returnat de ctre proprietate (aici
string, respectiv int) i numele proprietii (Nume i Varsta). Tipul proprietii,
este tipul cmpului pe care II gestioneaz proprietatea.
Corpul proprietii conine doi accesori: get i set. Unul din ei poate s lipseasc.
g e t are urmtoarele caracteristici:
v' Nu are parametri
v' Are tip de retur de acelai tip cu al proprietii.

s e t are urmtoarele caracteristici:


v' Are un singur parametru implicit, numit value, de acelai tip cu
proprietatea, value reine valoarea cmpului gestionat de proprietate.
s Are tipul de retur void.

Tipul proprietii Numele proprietii

public string Nume


{
get get nu are parametri. Retumeaz
{ o valoare de tipul proprietii
return nume;
}
set set nu are parametri explicii.
( Parametrul implicit este value
nume = value;
}
}

Accesorii pot fi declari n orice ordine. Nici o alt metod n afar de get i set nu
poate exista n corpul proprietii. Accesorii se apeleaz n mod implicit.

Citirea i scrierea ntr-o proprietate se face la fel ca pentru un cmp public:


Expresia c.Nume = "Andrei ; atribuie cmpului privat nume valoarea
"Andrei" n felul urmtor: set se apeleaz n mod implicit, iar parametrul
su implicit value, primete valoarea "Andrei". n corpul metodei, prin
nume = value; are loc atribuirea necesar.
Expresia c.Nume (scris n contextul unei afiri) retumeaz valoarea
proprietii, deci a cmpului nume, astfel: get se apeleaz n mod implicit.
Metoda get returnaz valoarea proprietii, deci a cmpului privat nume.

Proprietile nu ncalc principiul proteciei datelor


Aparent, un cmp declarat public (o practic descurajat n OOP) se
acceseaz n mod identic cu o proprietate asociat unui cmp privat, iar
proprietatea pare c nu protejeaz cmpul de aciuni nedorite. Nu este de loc aa.
n primul rnd avei libertatea s creai proprieti:
Read-Only, adic proprieti care nu implementeaz metoda get.
Write-Only, adic proprieti care nu implementeaz metoda set.
Nu putei defini o proprietate din care s lipseasc att get ct i set.
74 P artea I. L im bajul C #

n al doilea rnd, metoda s e t se poate implementa de asemenea manier,


nct cmpul asociat proprietii (backing field) s fie complet protejat de aciuni
nedorite.

Exemplu: t
n set putei plasa orice cod defensiv de protecie a cmpului asociat
proprietii:

using System;

class ntreg
{
private int n; // Cmp privat
public int N

get ( return n; } 1

set
{ // Cod care protejeaz n de aciuni nedorite
if {value > 1000) n = 1000;
else
if (value < 0) n = 0;
else n = value;
}

class Test
{
static void Main(string[] args)
{
ntreg i = new ntreg();
i.N = 1200; // set
Console.Write(i.N + " "); // get
i.N = -10; // set
Console.Write(i.N); // get
}
}

Ieire: 1000 0

Proprieti statice
Proprietile se pot declara static. Procedai astfel cnd dorii s le
asociai unor cmpuri statice. Proprietile statice nu pot accesa ali membrii ai
clasei, dect pe cei statici i exista independent de existena instanelor clasei. Se
acceseaz prin numele clasei, la fel ca ali membri statici.
C apitolul 4. Program are O rientat pe O biecte n C# 75

Exemplu:

class Numr
{
private static int nr; // Cmp static
public static int Nr // Proprietate static
t
get { return nr; }
set { nr = value; }
}
)

class TestConst
{
static void Main(string[] args)
{
Numr.Nr = 1 0 0 ; // set
System.Console.Write(Numr.Nr); // get
)
}

Convenie de notare
Pentru claritate, se obinuiete ca numele proprietii s fie acelai cu cel al
cmpului privat asociat. Diferena este c n timp ce cmpul ncepe cu liter mic,
proprietatea ncepe cu liter mare. Sfatul nostru este s urmai aceast convenie.

Proprieti implementate n mod automat

Aceste tipuri de proprieti, au urmtoarele caracteristici:

Nu se asociaz nici unui cmp al clasei.


Compilatorul aloc memorie pentru valorile furnizate, n funcie de tipui
proprietii.
Accesorii get i set nu au corp.
Nu pot fi read-only (nu poate lipsi get) i nici wrte-only (nu poate lipsi
set).

E xem plu:

using System;

class X
{
public int Valoare // Proprietate
{ // implementat
get; set; / / I n mod automat
}
>
76 Partea I. L im bajul C#

class TestAutoPropertie
{
static void Main(string[] args)
{
X x = new X ( ) ;
x.Valoare = 1 0 ; // set
Console.Write(x.Valoare); // get
}
}

Vei utiliza o proprietate automatic atunci cnd nu avei nevoie s impunei


restricii speciale valorilor sale.

Restriciile proprietilor
Proprietile nu definesc o locaie de memorie. Din acest motiv, nu pot fi
transmise cu modificatorii o u t sau r e f .
Nu pot fi suprancrcate.

Indexatori
Indexatorii permit instanelor unei clase sau ale unei structuri s fie indexate, i
la fel ca elementele unui tablou. Indexatorii i proprietile sunt similari din mai
multe puncte de vedere:
Sintax asemntoare.
Pot avea unul sau doi accesori.
Nu definesc o locaie de memorie.
Codul accesorilor poate s fie asociat sau s nu fie cu un cmp al
clasei.
Exist i diferene:
O proprietate acceseaz de regul un singur cmp privat, n timp ce
un indexator poate accesa mai muli membrii ai clasei.
Numele unui indexator este ntotdeauna this.
Un indexator este ntotdeauna un membru de instan. Din aceast^
cauz nu poate fi declarat static.
Sintax:
T i p R e t u r n a t this[int i n d e x ] -
{
get
{
/ / S e returneaz valoarea precizat prin index
>
set

// Se modific valoarea precizat prin index 1

T i p R e t u r n a t este tipul de baz al indexrii. Parametrul i n d e x primete valoareal


indexului elementului care va fi accesat. I
C apitolul 4. Program are O rientat pe O b iecte n C # 77

Exemplu:

using System;

class Tablou
{
private int[] a; // Tablou coninut - Cmp privat
private int n; // Dimensiunea tabloului
private const int MAX = 1000;

public Tablou(int dim) // Constructorul clasei


{
n = dim;
a = new int[n];
}
public int thisfint index] // Indexator
{
get // Returnez a[index] doar dac index este
{ // n intervalul [0, MAX]
if (index < 0)
return a[0];
else
if (index > MAX)
return a[MAX];
else
return a[index];
}

set // Seteaz afindex] doar dac index este


{ / / n intervalul [0, MAX]
if (index < 0)
a[0] = value;
else
if (index > MAX)
a[MAX] = v a l u e ;
else
a[index] = value;
}
>
}

class Testlndexer
<
static void Main(string[] args)
{
Tablou t = new T a b l o u (100);
for (int i = 0; i < 10; i++)
t[i] = i; // set
t[-l] = 10; // set
78 Partea I. Limbajul C#

for (int i * 0; i < 10; i++)


Console.Write(t[i] + " "); // get
}
1

Ieire:
10 1 2 3 4 5 6 7 8 9

n exemplul de mai sus se aplic operatorul [] referinei t , accesndu-se n felul


acesta elementele tabloului a, coninut n clas.
Dac o clas conine ca i cmp privat o colecie, iar acea colecie suport
operaia de indexare, atunci putei defini un indexator care v va permite s
accesai elementele coleciei cu ajutorul operatorui [] aplicat referinei la obiectul
de tipul clasei (mai sus, t [ i ] ).

Operatori de conversie
H
n capitolul 3, paragraful Conversii ntre tipuri, am vzut c ntre tipurile:
predefinite se pot face conversii implicite sau explicite. Conversiile explicite s e j
realizeaz cu ajutorului operatorului ( ) . 1
Exemplu:
double x = 2.3;
int y = 6;
x *> y; // Conversie implicii s
y = (double)x; // Converise explicii

i
C# v permite s definii un tip special de operatori n clase i structuri, care
realizeaz conversii implicite sau explicite ntre tipul clasei sau a structurii i alta
tipuri predefinite sau tipuri clas* sau struct. -i
Operatorii de conversie sunt metode statice, introduse cu cuvntul cheie
operator.

Sintax:
public static explicit operator T i p l (Tip2 t)

// Cod care convertete n mod explicit t spre T i p u l C l a s a i


> j

sau

public static implicit operator T i p l { T i p 2 t)


{ ;
// Cod care convertete n mod implicit t spre T i p u l C l a s m
) 1
Capitolul 4. Programare Orientat pe Obiecte n C# 79

Tipl este tipul spre care se face conversia. Tip2 este tipul care se convertete
spre Tipl. Unul dintre cefe dou tipuri trebuie s fie de tipul clasei sau structurii
care conine operatorul de conversie.

Exemplul 1:
Definim doi operatori care realizeaz conversii explicite de la tipul
Bancnota spre int i de la lnt spre tipul Bancnota:

// conversii_explicite.cs
using System;

claas Bancnota
{
private int valoare;

public Bancnota(int v) // Constructor


{
valoare = v;
}

/ / Operator de conversie explicit de la int la Bancnota


public static explicit operator Bancnota(int v)
{
return new Bancnota(v);
}

// Operator de conversie explicit de la Bancnota la int


public static explicit operator int(Bancnota b)
{
return b.valoare;
}
1

d a s s TestConversieExplicita
{
static void Main()
{
int val 100;
Bancnota b * (Bancnota)val; // Conversie explicit
Console.WriteLine ((int)b); // Conversie explcit
)
80 Partea I. Limbajul C#

Exemplul 2:
Modificm programul anterior, astfel nct s obinem operatori de conversii
implicite:

// conversii_implicite.cs
using System;

class Bancnota
{
private int valoare;

public Bancnota(int v) // Constructor


{
valoare = v;
}

// Operator de conversie implicit de la int la Bancnota


public static implicit operator Bancnota(int v)
{
return new Bancnota(v);
>

// Operator de conversie implicit' de la Bancnota la int


public static implicit operator int(Bancnota b)
{
return b.valoare;
}
}
clasa TestConversi.eImpli.cita
{
static void Main()
{
int val = 100;
Bancnota b = val; // Conversie implicit
Console.WriteLine (b); // Conversie implicit
}
>

Observai c nu a mai fost necesar utilizarea operatorului ( ) - type cas


operator.

Clase interioare

O clas interioar (inner class sau nested class) este o clas a crei definiie]
se gsete n interiorul definiiei altei clase.

1. Pentru a instania un obiect de tipulclasei interioare, nu este nevoie de un


obiect de tipul clasei exterioare:
Capitolul 4. Programare Orientat pe Obiecte n C# 81

Exemplu:

using System;

class A // Clasa container


{
public class B // Clasa interioar
{
public void F () { Console.W r i t e ("F()"); }
)
)

class TestlnnerClass
{
static void Main{)
{
A.B obj = new A.B(); // Creeaz un obiect de tip B
obj.F(); // Afieaz: F();
}
)

2. Metodele clasei interioare pot accesa toi membrii clasei care o conine, prin
intermediul operatorului ' . ' :

Exemplu:
using System;

public class Exterior


{
private int x;
public Exterior{int y) // Constructor
{
x = y;
}

public class Interior


{
public void Scrie(Exterior o)
{
// Acces permis la membrii clasei Exterior
System.Console.WriteLine (o.x);
>
}
}

public class TestlnnerClass


{
static void Main()
82 Partea I. Limbajul C#

Exterior ol ax new Exterior (100) ;

// Instanierea unui obiect de tip Interior


Exterior.Interior o2 ** new Exterior.Interior()
o 2 .Scrie(ol); // Afieaz: 100

Coninere

Cnd o clas are ca membri unul sau mai multe obiecte de tip clas, vorbim
despre conpnara (containment) sau compozlpa.
Tn figur, ilustrm clasa Calculator. Un
calculator are mai multe componente. Acestea sunt Calculator
instane ale altor clase : Monitor, Tastatura,
Mouse i UnitateCentrala. Monitor

Tastatur

Mouse

Unitate central
Exemplu:
Programul de mai jos definete trei clase:
Motor, Caroserie, Maina. Clasa Maina are ca
Figura 4.1 Coninere '
membri privai cte o referin spre obiecte de tip
Motor i Caroserie.

class Motor { /* ... */ )

class Caroserie { /* ... */ }

class Maina
{
private string marca;
// Maina ARE O caroserie c i ARE KW motor m
private Caroserie c;
private Motor m;
// Constructorul clasei
public Maina(Caroserie c, Motor m, string marca)
{
this.c = c;
this.m = m;-
this.marca - marca;
)
Capitolul 4. Programare Orientat pe Obiecte n C# 83

class TastContinaro
{
public static void Main()
i
Caroseria C nev Caroseria();
Motor M naw Motor();
Maina mea * naw Maina(C, M, "Volvo");
1
1

Clase pariale

Definiiile claselor, structurilor i interfeelor se pot mpri n mai multe fiiere


surs. Ca alternativ, putei fragmenta o clas n interiorul aceluiai fiier. Pentru a
separa n blocuri o definiie de clas, utilizai cuvntul cheie parial.
Exemplu:
using System;

partial class A
{
public void F{)
{
System.Console.Write ("F() ");
}
}

partial class A
{
public void 6()
{
System.Console.WriteLine("G()") ;
}
}

public class TestPartialClass


{
static void Main()
{
A a = naw A () ;
a.F() ;
.GO ;
}
}

Ieirea programului: F () G ()
84 Partea I. Limbajul C#

Practic, este vorba despre o singur clas cu numele A, a crei definiie a fost
fragmentat. Compilatorul unific definiiile pariale i instaniaz n mod corect
obiectul a de tip A.
Mediul Visual C# 2008 genereaz n mod curent asemenea definiii pariale.
Dac creai un proiect de tip Windows Forms, vei constata c definiia de clas a
formei principale, s-i spunem Forml, este fragmentat n dou fiiere diferite:
Form1.cs i Forml.Designer.cs.

Clase sigilate

sealed este un cuvnt cheie. Cnd modificatorul sealed este aplicat unei
clase, are efectul de a mpiedica alte clase s o moteneasc.

Exemplu:
sealed clasa A { / * . . . * / )

class B : A {/*...*/ } // Eroare

Suprancrcarea operatorilor
Toi operatorii unari i binari au implementri predefinite care sunt
disponibile n orice expresie n care sunt implicate tipuri predefinite. C# v permite
s redefinii semnificaia unui operator standard, astfel nct operatorul respectiv s
poat fi aplicat instanelor clasei voastre, tn acest fel sporii funcionalitatea
claselor.
Ce nelegem prin suprancrcarea operatorilor (operator overloading)? Este
un mecanism prin care instanele clasei pot fi integrate n expresii aritmetice sau
logice n calitate de operanzi, cu utilizarea operatorilor specifici tipurilor predefinite:
+, *, / , <, >, etc. Cnd definii o metod de tip operator, de exemplu pentru
operaia de adunare, atunci spunem c am suprancrcat operatorul +".
S presupunem c avem o clas care descrie o fracie i dorim s efectuam
operaii cu instane de tip Fracie, n felul acesta:

Fracie f1 = nev Fracie();


Fracie 2 = nev Fracie();
Fracie f = fl + f2;

n C# operatorii suprancrcai sunt metode statice ai crui parametri sunt


operanzii, iar valoarea retumat este rezultatul operaiei.
Sintaxa de declarare a unui operator pretinde folosirea cuvntului cheie
operator, urmat de simbolul operatorului care se redefinete.
Capitolul 4. Programare Orientat pe Obiecte n C# 85

Sintaxa
n cazul operatorilor binari:

public static T i p operator o p ( T i p l o p e r a n d l , Tip2 operand2)


{
// operaii
}

n cazul operatorilor unari:

public static T i p operator o p ( T i p o p e r a n d )


{
// operaii
}

op este operatorul care se suprancarc: +, /, etc.


Pentru operatorii unari, operandul trebuie s fie de acelai tip cu clasa
pentru care suprancrcai operatorul. Pentru operatoriibinari, cel puin unul dintre
cei doi operanzi trebuie s fie de tipul clasei. T i p este tipul de retur al operaiei i
de regul este un obiect de tipul clasei.

Suprancrcarea operatorilor binari


n exemplul de mai jos, clasa Fracie, suprancarc operatorii +, ==, !=:

I I fracie.cs
using System;

public class Fracie


{
private int numrtor;
private int numitor;
private static int Cmmdc(int a, int b)
{
if (b == 0) return a;
return Cmmdc(b, a % b ) ;
}
public Fracie (int numrtor, int numitor) // Constructor
{
int div = Cmmdc(numrtor, numitor);
numrtor /= div; numitor /= div;
this.numrtor = numrtor; .
this.numitor = numitor;
}

public static Fracie operator + (Fracie fl, Fracie 1 2 )


{
int A = fl.numrtor * f2.numitor +
f2.numrtor * fl.numitor;
86 Partea I. Limbajul C#

int B = f1.numitor * f2.numitor;


int cmmdc = Cmmdc(A, B ) ;
A /= cmmdc;
B /= cmmdc;
return new Fracie(A, B ) ;
>

public static bool operator (Fracie fl, Fracie f2)


{
if (fl.numitor == f2.numitor &&
fl.numrtor == f2.numrtor)
return true;
return false;
}

public static bool operator !=(Fracie fl, Fracie f2)


{
return !(fl 3= f2);
}

// Suprascrie Object. ToStringO


public override string ToStringO
(
String s =* numrtor.ToStringO + "/" +
numitor.ToString() ;
return s ;
}

public class TestFractie


{
static void Main()
{
Fracie a = new Fracie(3, 4);
Console.WriteLineO'a = (0)", a.ToStringO );
Fracie b new Fracie(2, 4);
Console.WriteLine("b = (0), b . T oStringO );

Fracie c a + b; // operatort
Console.WriteLine("c = a + b = {0}",
c.ToString());
Fracie d = new Fracie(2, 4);

if (d = b) //operator==
Console.WriteLine("d = b = {0}", d) ;

if (a H b) //operator!
Console.WriteLine(a + " != " + b);

a += b; // operator +3=
Capitolul 4. Programare Orientat pe Obiecte n C# 87

Console.WriteLine("a = " + a ) ;
}
}

Ieire:
a = 3/4
b * 1/2
e = a + b * 5/4
d = b = 1/2
3/4 != 1/2
a = 5/4

De reinut:
> Operatorul de atribuire = nu se suprancarc. El este furnizat n mod
implicit de ctre compilator (e * a + b).
> Operatorii unari au un parametru, iar cei binari doi parametri: n ambele
cazuri, cel puin unul dintre operanzi trebuie s fie de tipul clasei sau al
structurii.
> Operatorii unari au un singur parametru.
> C# pretinde ca n situaia n care suprancrcai = atunci trebuie s
suprancrcai i !=. Similar, operatorii < i > trebuie suprancrcai n
perechi, la fel ca i <= cu >=.
> Dac suprancrcai operatorul +, atunci C# sintetizeaz automat +=.
Aceeai regul este valabil i pentru + cu +=, * cu *= , etc.

Metoda ToString()
n clasa Fracie, am definit metoda ToStringO . De fapt, am redefinit
pentru Fracie, aceast funcie. ToStringO este o metod a clasei object,
clasa de baz a tuturor claselor. Rolul ei este de a retuma o reprezentare a
obiectului clasei ntr-un obiect de tip string. De cte ori dorii o conversie
particular spre string a obiectelor clasei, redefinii aceast metod motenit.
Pentru aceasta folosii cuvntul cheie overrida. Observai c metoda
ToStringO se apeleaz n mod implicit atunci cnd transferai obiectul ntr-un
context n care se cere un string: apelul Console .WriteLine ("a = + a);
pune a ntr-un context n care se ateapt un string, deci a se convertete la
string prin apelul implicit al metodei ToStringO

Suprancrcarea operatorilor unari


Pentru exemplificarea suprancrcrii operatorilor unari definim o clas simpl:

using System;

public class ntreg


{
88 Partea I. L im bajul C #

private int n;
public ntreg(int i) // Constructor

1 ;

}
// Operatorul de incrementare
public static ntreg operator + + (ntreg x)
{
return new ntreg(++x.n);
>
// Operatorul unar -
public static ntreg operator - (ntreg x)
{
return new ntreg(--x.n) ;
}
public override string ToStringO
{
String s = string.Format("{0}1 n) ;
return s;

m
}

public class TestOpUnari


{
s t a t i c v o i d H a i n ()
{
ntreg x = new ntreg(10);
x++; // Incrementare
Console.WriteLine (x + " " + -x); // Scrie: 11 -11
}
}

NOTA:
Nu este nevoie s creai dou versiuni diferite ale operatorului ++ ca_
suporte incrementare prefixat i sufixat. O singur versiune este suficient,
compilatorul are grij s implementeze diferenierea ntre prefixare i sufixare.

IMPORTANT
Este recomandabil s nu modificai operanzii pasai m etodelor o p e ra to ri
loc de aceasta, creai noi instane de tipul valoni de retur i returnai ace|
instane. Urmnd aceast practic, vei evita probleme la depanare.

Operatorii care pot fi suprancrcai:

Operatori unari: ++, , true, false


Operatori binari: +, * , / , %, &, | , A, ,
C apitolul 4. P rogram are O rientat pe O biecte n C# 89

| Operatori relaionali: = cu !=, < cu >, <= cu >= (acetia trebuie suprancrcai n
perechi).

Aciuni nepermise la suprancrcarea operatorilor:

> Crearea unui nou operator (se pot suprancrca doar operatori predefinii).
> Schimbarea sintaxei unui operator.
> Redefinirea modului de lucru a unui operator cu tipuri predefinite.
> Schimbarea precedenei sau asociativitii unui operator.

Structuri

Structurile sunt tipuri de date definite de programator, asemntoare


claselor. Se definesc cu ajutorul cuvntului cheie struct.
Structurile sunt asemntoare claselor prin faptul c pot s conin cmpuri,
-metode, constructori, proprieti, operatori, tipuri imbricate, indexatori.
| Difer de clase n urmtoarele privine:
P - Structurile sunt tipuri valoare, iar clasele sunt tipuri referin.
| - Nu suport motenirea.
Nu suport constructori fr parametri.
Nu au destructori.

iSintaxa:
{M o d i f i c a t o r A c c e s ] struct N um eStcuctur

// membrii structurii
a

xemplu:
sing System;

truct Punct

private double x;
private double y;

public Punct(double x, double y) // Constructor


{
x = _x ;
y = _ jy ;
}

public double X // Proprietatea X


{
get { return x; }
90 P artea I. L im bajul C#

set { x = v a l u e ; }
}
public double Y // Proprietatea Y
1
get { return y; }

set ( y = value; }
}
}

class Teststruct
{
static void Main(string[] args)
{
Punct pi = new P u n c t (2.3, 3.5);
Console.Write("x = {0}, y = {1}", pl.X, pl.Y);
)
)

Structurile sunt recomandabile pentru obiecte mici, aa cum este un obiect de tip
Punct, care trebuie instantiate n numr mare, eventual ntr-o bucl. Pentru c
sunt tipuri valoare, se construiesc pe stiva programului, care se acceseaz mai
rapid dect memoria Heap.

Interfee
i

O interfa este un tip referin care descrie un set de metode, dar nu le


implementeaz. Clasele i structurile pot implementa interfeele. Cnd o clas
implementeaz o interfa, trebuie s implementeze toate metodele acelei
interfee. n felul acesta, clasa "semneaz un contract", pe care se oblig s-l
respecte.

Sintaxa minimal:
[ m o d i f i c a t o r i ] interface N u m e l n t e r f a
{
// Corpul interfeei
}

Modificatorii pot fi public, private, protected, internai, protected


i n t e r n a i . Cuvntul cheie interface preced numele interfeei. Este o practic
comun ca numele interfeei s nceap cu litera I. Exemple: Icomparable,
ICloneable, IControl, etc.

Implementarea interfeelor de ctre clase


O clas sau o structur poate implementa una sau mai multe interfee, ca
mai jos:
C apitolul 4. Program are O rientat pe O biecte n C# 91

interface II { /*...*/ }
interface 12 { /*...*/ }

class C : II, 12
{ /*...*/ }

Exemplu:

using System;

interface IPrintable
{
void Prin(string s) ;
}

public class Mail : IPrintable


{
private string s;
public Mail(string s) // Constructor
{
this.s = s;
}
// Implementarea metodei interfeei (obligatoriu!)
public void Prin(string a)
{
Console.WriteLine(s + a);
}
)

public class TestOpUnari


{
static void Main()
{
Mail m = nev Mail("Prietenilor mei ");
m.Prin("Salut!");
}
>

Ie ire :
Prietenilor mei Salut!

Ceea ce trebuie s reinei despre interfee e s te :.

> O interfa nu se poate instania.


> Interfeele nu conin cmpuri, ci doar metode, proprieti, evenimente.
> interfeele nu conin implementri ale metodelor.
> Clasele i structurile pot moteni (impelmenta) una sau mai multe interfee.
> O interfa poate la rndul ei s moteneasc o alt interfa.
92 P artea I. L im bajul C#

M otenire
Motenirea este unul dintre cele mai importante i mai puternice concepte n
Programarea Orientat pe Obiecte. Motenirea v permite s definii o nou clas
care incorporeaz i extinde o clas existent.
Diagrama de mai jos prezint o ierarhie de clase bazat pe motenire. Un
animal este o fiin, un om este o fiin, un cine este un animal, un brbat este
om, .a.m.d. Vom generaliza cu afirmaia urmtoare:

Motenirea modeleaz relaia IS A (ESTE UN, ESTE O).

Spunem c Om i Animal motenesc clasa Fiina. Ele sunt clase


derivate din clasa Fiina, iar aceasta din urm este clas de baz pentru Om i
Animal. Un obiect de tipul clasei derivate, conine ca s u b o b ie ct, un obiect de tipul '

Figura 4.2 Ierarh ie de clase bazat pe motenire

clasei de baz. Aadar, un obiect de tip Om conine ca subobiect un obiect de tip


Fiina, iar un obiect de tip Femeie, conine un subobiect de tip Om, care la rndul
su include un subobiect de tip Fiina.

Specializare i generalizare

Una dintre cele mai importante relaii ntre obiecte n lumea real este
specializarea, care poate fi descris ca o relaie /S A. Cnd spunem c un cine
esfe un animal, ne gndim de fapt c un cine este un tip specializat de animal.
Cinele este un animal pentru c are toate caracteristicile unui animal, dar
specializeaz aceste caracteristici conform speciei sale. O pisic esfe un animal,
deci are n comun cu cinele caracteriscticile animalelor (ochi, gur, etc) dar difer
fa de un cine prin caracteristici specifice pisicilor.
Pe de alt parte, tipul Animal, generalizeaz tipurile Pisic i Cine.
Aceste relaii sunt ierarhice. Ele formeaz un arbore. Urcnd n arbore,
generalizm; cobornd, specializm.
C apitolul 4. Program are O rientat pe O biecte n C # 93

Motenirea presupune att specializare ct i generalizare. n C#, dubla


relaie de specializare i de generalizare este implementat folosind principiul
motenirii.

Implementarea motenirii

Fie clasa A care motenete clasa B. Operatorul : exprim relaia de


motenire:

class B // B - Clasa de baz


{
// Membrii clasei B
}

class A : B / / A - Clasa derivat


{
// Membrii clasei A
>

Sintaxa A :B se numete specificaie de clas de baz (base class specification).

M em brii clasei d erivate sunt:


> Membrii definii n propria clas.
> Membrii clasei de baz.

Se spune despre o clas c e xtin d e clasa sa de baz, pentru c include membrii


clasei de baz, plus orice caracteristic i funcionalitate suplimentar furnizat de
propria declarare.
Clasa b din figura 4.2 are un cmp i o metod. Clasa A, n dreapta, i
definete proprii membri: un cmp i o metod i n plus motenete clasa B, deci
are un cmp i o metod suplimentare pentru c un obiect de tip A include un
subobiect de tip B.

Figura 4.3. Clasa A motenete clasa B


94 P artea I. L im bajul C#

IMPORTANT
n C# toate clasele sunt clase derivate. Oricare clas deriv n mod direct
sau indirect din clasa object. Dac o clas nu specific n mod explicit
derivarea dintr-o alt clas, atunci ea motenete direct clasa object. In felul
acesta, object este baza tuturor ierarhiilor de clase.

Exemplu:
Cele dou declarri ale clasei Avion specific acelai lucru: faptul c Avion
deriv din object:

// Derivare implicit // Derivare explicit


// din object // din object
class Avion class Avion : object
{ {
// membrii clasei // membrii clasei
} }

Alte cteva aspecte trebuie reinute n legtur cu motenirea n C#:

> O clas poate moteni o singur alt clas i oricte interfee


n C# o clas poate moteni o singur clas de baz. Acest tip de motenire se
numete motenire singular (single inheritance).
0 clas C# poate moteni n schimb, oricte interfee.
Fie clasele A i B i interfeele l, 12, 13. Dac A motenete b i interfeele
l, 12,13, atunci n lista care specific relaia de motenire, clasa B trebuie s
fie precizat naintea interfeelor:

// Corect // Incorect
class A : B, II, 12, 13 class A : II, B, 12, 13
{ {
1 }

> C# nu admite motenirea m ultipl


Motenirea multipl (multiple inheritance) are loc atunci cnd o clas are mai
multe clase de baz. Dintre limbajele importante, doar C++ suport acest tip
de motenire.

// Incorect n C#
class A : B, C, D
{
}

> nlimea arborelui relaiilor de motenire poate fi orict de mare


Mai jos, A, B, i c sunt clase. Rdcina ierarhiei este object. Din object
deriv D, din D deriv c, din c deriv B, iar din b deriv A:
C apitolul 4. P rogram are O rientat pe O biecte n C# 95

// Corect
class C :D { }
class B :C { }
class A :B { }

Accesarea membrilor motenii

O instan a unei clase motenete toi membrii clasei de baz, cu excepia


constructorilor. Totui accesul la membrii clasei de baz poate fi restricionat, cu
ajutorul m odificatorilor de acces. Acetia sunt: public, private, protected,
internai i protected internai Programul urmtor, testeaz modul n care
modificatorii de acces controleaz modul de acces la membrii clasei de baz.

using System;

class Animal // Clasa de baz


{
private string hrana; // Cmpuri
protected int speranta_viata;
public string Hrana // Proprietate
{
set { hrana = value; }
get { return hrana; }
}
protected void SeHranesteO // Metod
{
Console.WriteLine("Animalul se hrnete");
}
}

class Pisica : Animal // Pisica - clas derivat


{
private string rasa;
public string Rasa
{
set { rasa = value; }
get { return rasa; }
>
public void T oarce()
<
/* Membrii protejai i cei publici ai clasei de baz
pot fi accesai din metodele clasei derivate */

// hrana = "lapte"; // Eroare! -cmp privat


speranta_viata = 12; // Corect! -cmp protejat
Hrana = "lapte"; // Corect! -proprietate public
Se H r a nest e O ; // Corect! -metod protejat
Console.WriteLine("Pisica toarce");
}
96 P artea I. L im bajul C#

public class TestAccesMembri


{
static void Main()
1
Animal a = new A n i m a l ();
// a.hrana = "carne"; // Eroare! -cmp privat
// a .speranta_viata = 10; // Eroare! -cmp protejat
a.Hrana = "carne"; // Corect! -proprietate public
// a .SeHraneste(); // Eroare! -metod protejat

/* Toi membrii clasei Animal sunt membri ai clasei


Pisica. Membrii private i protected nu pot fi
accesai din exteriorul clasei Pisica */

Pisica p = new P i s i c a ();


// p.hrana = "lapte"; // Eroare! -cmp privat
// p .speranta_viata = 12; // Eroare! -cmp protejat
p.Hrana = "lapte"; // Corect! -proprietate public
// p.SeHraneste(); // Eroare! -metod protejat
// p.rasa = "siameza"; // Eroare! -cmp privat
p.Rasa = "Siameza"; // Corect! -proprietate public
p .T o a r c e (); // Corect! -metod public

Ieire:
Animalul se hrnete
Pisica toarce

Se desprind urmtoarele reguli:


Metodele unei clase au acces la toi membrii declarai In acea clas,
indiferent de nivelul de protecie a membrilor.
Metodele clasei derivate pot accesa membrii publici i pe cei protejai ai
clasei de baz.
Metodele clasei derivate nu pot accesa membrii privai ai clasei de baz.
Din exteriorul clasei derivate i a celei de baz, se pot accesa numai
membrii publici ai clasei de baz. Membrii protejai se comport n acest
caz la fel ca cei privai.

Membrii unei clase marcai cu modificatorii internai, sunt vizibili (accesibili)


pentru toate clasele din acelai fiier sau din acelai assembly.
Membrii unei clase marcai protected internai sunt vizibili tuturor care o motenesc
i n plus, tuturor claselor din acelai assembly.
C apitolul 4. P rogram are O rientat pe O b iecte n C# 97

Constructorii claselor derivate


Constructorii clasei de baz nu se motenesc. Constructorul clasei derivate
apeleaz n schimb constructorul bazei, pentru a construi poriunea din obiect
specific bazei.
Exemplu:

using System;

class Baza
{
p ubl i c B a z a ()
{
Console.WriteLine("Constructor B a z a " ) ;
}
)

class D e r i v a t : Baza
{
pub l i c D e r i v a t ()
{
Console.Wri t eLine("Constructor Derivat");
}
}

public class Te s t C o n s t r u c t o r
{
static v o i d Main()
{
Derivat d;
d = n e w Derivat(); // Apelul constructorului clasei
} // derivate
1

Ieire:
Constructor Baz a
Constructor D e r i v a t

Exemplul de mai sus pune n eviden faptul c la construirea unei instane a


clasei, constructorul D e r i v a t () execut constructorul clasei B a z a naintea
executrii propriului cod. Are loc un apel im plicit al constructoului fr parametri
Baza).
Limbajul C# permite i a p e lul e x p lic it al constructorului bazei. Sintaxa
corespunztoare este:
4-------
public D e r i v a t () : b a s e ()
{
98 P artea I. L im bajul C #

Dac constructorul bazei are parametri, atunci apelul implicit nu poate avea loc.
Constructorul derivat trebuie s invoce n mod explicit constructorul bazei,
fumizndu-i i argumentele corespunztoare:
Exemplu:

using System;

class Baza
t
private int x;
public Baza(int y)
{
x = y;
}
}

class Derivat : Baza


{
private char c;
public Derivat(char a, int b) : base(b)
{
c = a;
}
}

public class TestConstructor


{ t
static void Main{)
{ '
Derivat d = new Derivat('T', 10);
} 1
} -3
- ?
m
Constructorul clasei derivate trebuie s aib suficieni parametri pentru a iniializa
i cmpurile bazei. j
|
Cum se construiete o instan a clasei derivate ? *
Cnd se invoc constructorul clasei derivate, ordinea construciei instanei este: J

1. Iniializarea membrilor de tip instan a clasei derivate. J


2. Apelul constructorului clasei de baz. .23
3. Executarea corpului constructorul clasei derivate. l
'd
n cazul n care lanul ierarhic al motenirii conine mai multe clase, atunci fiecare ^
constructor i execut mai nti constructorul bazei sale naintea propriului corp.
C apitolul 4. P rogram are O rientat pe O biecte n C# 99

Membrii ascuni
Dac n clasa derivat avei un cmp cu acelai nume cu al unuia din clasa
de baz, sau avei o metod cu aceeai signatur (acelai nume i aceeai list de
parametri formali) cu a uneia din clasa de baz, atunci numele membrilor din clasa
de baz sunt ascunse metodelor clasei derivate. Pentru a accesa membrii ascuni
ai bazei, se ntrebuineaz new n faa membrilor bazei i cuvntul cheie base,
pentru accesarea membrilor ascuni.

Exemplu:

using System;

class Baza
{
public int camp = 10;
public void M e t o d a ()
{
Console.WriteLine("Baza.MetodaO");
}

class Derivat : Baza

new public int camp = 20;


new public void M e t o d a ()
{
base .Metoda () ;
Console.WriteLine("Derivat.Metoda O " + base.camp);

f public class TestMembriAscunsi

static void Main)


{
Derivat d = new D e r i v a t ();
d . Metoda();

>

Ieire:

B a za .M e to d a ()
| Derivat.Metoda() 10
| Baza.Metoda ()

I
100 Partea I. L im bajul C#

P o lim orfism

Polimorfismul este unul dintre conceptele fundamentale ale programrii


orientate pe obiecte. Reprezint caracteristica unei entiti de a se comporta n
moduri diferite, n funcie de context. n particular, este caracteristica unei variabile
referin de a putea referi obiecte de tipuri diferite. C# admite polimorfismul bazat
pe motenire. Acest tip de polimorfism v permite s invocai runtime metode ale
claselor derivate cu ajutorul unei referine la clasa de baz.

Conversia referinelor
Dac avei o referin la un obiect al clasei derivate, putei obine o referina
la partea de baz a obiectului, folosind operatorul de conversie () ca mai jos:

class Baza
{
public void M e t o d a ()
{
System.Console.WriteLine("Baza.Metoda()");
}
}

class Derivat : Baza


{
public void M e t o d a () // sau new public void M e t o d a (>
{
System.Console.WriteLine("Derivat.M e t o d a ()");
}
>

public class TestConversieRef


{
static void Mainf)
{
Derivat d = new Derivat();
d.Metodaf);

// XJpcast
Baza b = (Baza)d;
b.Metoda ();
}
}

Ieire:
Derivat.M e t o d a ()
Baza.Metoda()
C apitolul 4. Program are O rientat pe O biecte n C# 101

Se constat c referina la
partea de baz a obiectului nu
poate vedea" restul obiectului
clasei derivate, deoarece
privete printr-o referin b la
clasa de baz. Prin b vei
putea s invocai numai
Metoda () clasei de baz.

Conversia unei referine a unui


obiect derivat spre o referin
la clasa de baz se numete
upcast.

Metode virtuale
n paragraful anterior am artat c ntr-o clas derivat putei defini o metod
cu acelai prototip cu al unei metode din clasa de baz, dar c o referin la un
obiect de tipul clasei de baz nu poate invoca noua metod definit cu new.
Pentru ca o referin la un obiect al bazei s poat accesa membri ai
obiectelor derivate, altfel spus, pentru a obine polimorfism bazat pe motenire,
este nevoie de urmtoarele:
> Clasa de baz declar acel membru virtual.
> Clasa derivat redefinete acel membru, cu exact aceeai semntur i tip
de retur, adugnd cuvntul cheie override, naintea tipului de retur.
Exemplu:

using System;
namespace Polimorfism
{
class Baza
{
virtual public void M e t o d a ()
{
Console.WriteLine("Metoda() din Baza");
}
}
class Derivat : Baza
{
override public void M e t o d a ()
{
Console.WriteLine("Metoda() din Derivat");
}
}
class TestPolimorfism
{
static void Main(string[] args)
102 P artea I. L im b aju l C #

{
Derivat d = new Der iv a t ();
d.Metoda(); // Ieire: " Met o d a Q din Derivat"
// Polimorfism
Baza b = new B a z a ();
b . M e t o d a (); // Ieire: " Met o d a O din Baza"
b = new D e r i v a t ();
b.Metoda{) ; // Ieire: "MetodaO din Derivat"
}
}
}

Primul apel b . M e t o d a O ; invoc metoda din clasa de baz, deoarece tipul


referinei este Baza i tipul obiectului referit este Baza. Al doilea apel invoc
metoda redefinit n clasa derivat. Referina b este n continuare de tip Baza, dar
tipul obiectul referit este de tipul clasei derivate. Acesta este manifestarea
polimorfismului bazat pe motenire.
n cazul unui lan de derivare care pornete de la o clas de baz cu metode
virtuale, n clasele derivate avei opiunea de a redefini sau nu acele metode.
Exemplu:

using System;
class A
{
.virtual public void F()
{ Console.WriteLine("FO din A"); }
>

class B : A { } // B nu redefinete F()


class C : B
{
override public void F()
{ Console.WriteLine("F() din C"); }
}

class D : C { } // D nu redefinete F()

class Test
{
static voi d Main(string[] args)
{
A a = new B{) ; // a refer un obiect de tip B
a.F() ; // Ieire: "F( ) din A"
a = new C () ; // a refer un obiect de tip c
a . F () ; // Ieire: "'F() din C"
a = new D () ; // a refer un obiect de tip D
a.F() ; / / Ieire: "' FO din C"1
}
}
C apitolul 4. P rogram are O rientat pe O biecte n C # 103

Dac o referin de tipul ciasei de baz refer un obiect de tip derivat i prin acea
referin invocai o metod virtual, atunci se apeleaz cea mai apropiat metod
override definit pe lanul ierarhic. Dac nu exist metode redefinite, atunci se
invoc metoda virtual din clasa de baz.

Restricii
Reinem urmtoarele aspecte:
Se pot declara virtual urmtorii membri: metode, proprieti,
evenimente i indexatori.
Cmpurile nu pot fi declarate v i r t u a l .
Metodele redefinite cu override trebuie s aib acelai nivel de
accesibiliate cu metodele virtuale corespunztoare. De exemplu nu este
corect ca o metod virtual declarat public s fie redefinit cu o
metod declarat private.
Nu se pot redefini metodele non-virtuale.
Nu pot fi redefini metodele statice.

Modificatorul sealed
Aplicat unei clase, modificatorul sealed mpiedic alte clase s o
moteneasc, sealed poate fi aplicat i unei metode sau unei proprieti care
redefinete o metod sau o proprietate a clasei de baz. n aceast situaie, se
permite altor clase s moteneasc clasa care are un membru sealed, dar
metoda sau proprietatea sealed nu mai poate fi redefinit n clasele derivate.
Exemplu:

class A
1
protected virtual void F() { /*...*/ }
protected virtual void G{) { /*...*/}
}

class B : A
{
sealed protected override void F() { / * . . . * / }
protected override void G() { /*...*/ }
}
class D : B // Corect. B poate fi motenit
{
protected override void F() { /*...*/ } // Eroare !
protected override void G() { /*...*/ } // Corect
}

Cnd se aplic unei metode sau unei proprieti, modificatorul sealed trebuie s
fie folosit ntotdeauna cu override.
104 P artea I. L im bajul C# C apitolul 4. Program are O rientat pe O biecte n C# 105

Utilitatea polimorfismului Tabloul LimbaVorbita reine referine ale unor obiecte de tipuri diferite, dar care
n practic se opereaz deseori cu colecii de obiecte. Mai precis, cu colecii sunt legate prin relaie de motenire, avnd ca baz a ierarhiei clasa
de referine la obiecte. Dac obiectele sunt legate printr-o relaie de motenire LimbaVorbita. Dac relaia de motenire nu ar exista, atunci referinele ar fi
avnd o clas de baz comun, atunci nu trebuie ca ele s fie de acelai tip- Dac trebuit s fie de acelai tip. Programul implementeaz polimorfismul. Interfaa de
toate obiectele redefinesc o metod virtual a clasei de baz, atunci putei invoca apelare unic ( lv.SeVorbeste) ) care se utilizeaz pentru fiecare obiect, duce
aceast metod pentru fiecare obiect. la aciuni specifice, n funcie de obiectul referit.

using System;
class LimbaVorbita // Clasa de baz
R ezu m a tu l c a p ito lu lu i
virtual public void SeVorbeste) { } // nu va fi invocat
Clasele sunt entiti logice care modeleaz obiecte din lumea real sau
obiecte abstracte. Clasele ncapsuleaz date i metode care opereaz cu
class Engleza : LimbaVorbita aceste date.
Constructorii unei clase sunt metode speciale care au rolul de a creea, a
override public void SeVorbeste)
construi obiecte.
{ Console.WriteLine("Engleza"); }
* Destructorul clasei este o metod special care distruge instanele
claselor.
class Franceza : LimbaVorbita
Proprietile sunt membri ai clasei cu ajutorul crora se acceseaz
override public void SeVorbeste() cmpurile private ca i cnd ar fi fost declarate public,.fr ca prin aceasta
{ Console.WriteLine("Franceza"); } : s se ncalce principiul proteciei datelor.
Suprancrcarea operatorilor este mecanismul prin care instanele clasei
class Spaniola : LimbaVorbita pot fi integrate n expresii aritmetice sau logice n calitate de operanzi, cu
utilizarea operatorilor specifici tipurilor predefinite: +, * , / , <, >, etc.
override public void SeVorbeste) Motenirea este mecanismul care permite s s se defineasc o nou
{ Console.WriteLine("Spaniola"); ) clas care incorporeaz i extinde o clas existent.
* Polimorfismul este caracteristica unei variabile referin de a putea referi
lass Catalana : Spaniola obiecte de tipuri diferite. C# admite polimorfism bazat pe relaia de
motenire.
override public void SeVorbeste)
{ Console.WriteLine("Catalana"); }
n treb ri i ex erc iii

class Test 1. Care este diferena dintre un obiect i o clas ? Dar dintre o referin i un
obiect ?
static void Main(string[] args) 2. Indicai principalele deosebiri care exist ntre membrii statici i cei nestatici
{ ai unei clase.
LimbaVorbita[] L = new LimbaVorbita[4]; 3. Ce relaie se modeleaz ia motenire ? Dar la coninere ?
L [0] = new Engleza); L[l] = new Franceza); 4. Implementai o clas cu numele Persoana i o a doua clas cu numele
L [2] = new Spaniola); L[3] = new Catalana);
E le v . Clasele trebuie s aib constructori, cmpuri private i proprieti.
5. Scriei o clas cu numele BigNumber care implementeaz operaii cu
foreach (LimbaVorbita lv in L)
lv.SeVorbeste(); numere mari. Suprancrcai cel puin operatorii de adunare, scdere i
nmulire.
}
}
Ieire:
Engleza
Franceza
Spaniola
Catalana
106 P artea I. L im bajul C#

C apitolul 5

Trsturi eseniale ale limbajului C#


Acest capitol prezint delegrile, evenimentele, genericele, coleciile,
mecanismul de tratare a excepiilor n C#, un subcapitol dedicat manevrrii
stringurilor i un paragraf care se ocup de operaiide intrare i ieire cu
fiiere text.

D eleg ri

O delegare este un tip referin, utilizat s ncapsuleze o list ordonat de


metode cu aceeai semntur i acelai tip de retur. Lista de metode se numete
lista de invocare. Cnd un delegat este invocat, el apeleaz toate metodele din
lista de invocare. O delegar cu o singur metod n lista sa este similar cu un *
pointer la funcii n C++, ns o delegare este un tip referin i ofer sigurana I
tipurilor (type-safe). Capacitatea unei delegri de a invoca mai multe metode se
numete m ulticasting. i

Declarare !
r
O delegare este un tip, aa cum i clasele sunt tipuri. Un tip delegare f
trebuie declarat nainte de crearea obiectelor de tipul su. Declararea este creat f
cu cuvntul cheie delegate, urmat de tipul de retur i de signatura metodelor pe j
care delegarea le accept. *
Exem plu:

d e l e g a t e v o i d D e l e g a r e a M e a ( i n t x) ;

Expresia declar tipul delegat D e l e g a r e a M e a . Obiectele de tipul acesta vor


accepta numai metode cu un singur parametru de tip i n t i cu tipul de retur void.
Tipurile delegat nu au corp. j

8
*

Crearea obiectelor delegare ' f


O delegare este un tip referin. Un asemenea tip, conine referina spre j,
obiect, i obiectul propriuzis.
|
R eferinele (aici, referina se numete d) se declar simplu:

D e l e g a r e a M e a d;
j
s
'
O biectele de tip delegare se creeaz n dou moduri :
' l'
1. Cu sintaxa specific instanierii obiectelor:
C apitolul 5, Trsturi eseniale ale lim bajului CU 107

d = new DelegareaMea(ReferinObiect.Metod) ;
sau
d = new DelegareaMea(NumeCXas.MetodStatic) ;

Este important de reinut ca delegrile pot ncapsula att metode de


instan ct i metode statice.
2. Cu sintaxa simplificat, care necesit doar precizarea metodelor ataate
delegrii:

d = R e fe rz n O b ie c t.M e to d ;
sau
d = N v m e C la s .M e to d S ta tic ;

Invocarea metodelor ataate unei delagri


Prezentm un exemplu care declar un tip delegat i o referin la cest tip.
Apoi ataeaz delegrii cateva metode i n cel din urm le invoc.

using System;

class Simplu
{
// Metod de instan care potrivete delegrii
public void F (string s)
{
Console.WriteLine(S + "F() " ) ;
}
// Metod static care potrivete delegrii
public static void G(string s)
{
Console.WriteLine(s + "G() ");
)
}

// Declar tipul delegat Del


delegate void D e l (string s) ;

class Program
{
static void Main()
{
Del d; // Declar o referina de tip Del
Simplu s = new Simplu();

// Acum atam metode delegrii d


d = s.F; // Lista de invocare: F()
d += Simplu.G; // Lista de invocare: F(), G()
d += Simplu.G; // Lista de invocare: F(), G(), G()
108 P artea I. L im bajul C#

// Delegarea d invoc acum toate metodele din list


d("Prima invocare: ");

d -= s.F; // Lista de invocare: G()


d {"A doua invocare: ");
}
)

Ieire:
Prima invocare: F ()
Prima invocare: G()
Prima invocare: G()
A doua invocare: G ()
A doua invocare: G ()

Exemplul anterior descrie modul n care putei atribui o metod listei de invocare a
delegrii, cu operatorul de atribuire =, apoi putei aduga sau elimina alte metode
cu acelai prototip cu operatorii += sau -= .

Invocarea delegrilor cu tipuri de retur


Dac o delegare are o valoare de retur i mai mult de o metod n lista de
invocare, atunci valoarea care se returneaz n urma invocrii delegrii este
valoarea returnat de ultima metod din lista de invocare. Valorile de retur ale
tuturor celorlalte metode din list sunt ignorate.
Exem plu:

using System;

// Declar tipul delegat DelTest


delegate int De l T e s t ();

class Test
{
private int x = 0;
// Metode cu acelai prototip cu al delegrii
public int F ()
{
x += 2;
return x;
}
public int G ()
{
x + = 6;

return x;

class Program
{
C apitolul 5. Trsturi eseniale ale lim b a ju lu i C # 109

static void Main()


{
Test s = new T e s t Q ;
DelTest d; // Referin la tipul delegat

// Atam metode delegrii d


d = s.F; // Lista de invocare: F()
d += s.G; // Lista de invocare: F O , G()
d += s.F; // Lista de invocare: F ( ) , G ( ) , F()
Console.WriteLine(d()); // Afieaz: 10

Evenim ente

J ||l: Aplicaiile cu interfa grafic cu utilizatorul sunt sensibile la evenimente ca:


I I I click cu mouse-ul pe suprafaa unei ferestre, apsarea unei taste, deplasarea
mouse-ului deasupra unui control, etc. Sistemul de operare ntiineaz fereastra
| j j | activ despre apariia unei aciuni, iar programatorul poate decide dac va trata
| acest eveniment. Evenimentele pot avea o mare diversitate i nu sunt ntotdeauna
| | cauzate de o aciune direct a utilizatorului aplicaiei; de exemplu curgerea unui
interval de timp, terminarea copierii unor fiiere, primirea unui mail.

Evenimentele C# permit unei clase sau un obiect s notifice, s ntiineze


alte clase sau obiecte c ceva s-a ntmplat.

n terminologia specific, clasa care semnaleaz evenimentul se numete


publisher, iar clasele care sunt informate despre faptul c a avut loc evenimentul
se numesc subscribers. Clasele care subscriu evenimentului (clasele subscriber)
definesc metode pentru tratarea acestui eveniment (event handler-e).
Exis o mare asemnare ntre delegri i evenimente.
Un eveniment este un membru public al clasei care public evenimentul.
Atunci cnd are loc o aciune, acest membru al clasei publisher se activeaz,
invocnd toate metodele care au subscris evenimentului. Activarea se numete
declanare (firing the event).

Lucrul cu evenimente

Pentru utilizarea evenimentelor, programatorul trebuie s scrie cod dup cum


urmeaz:
1. Declar un tip delegat. Aceast declarare poate avea loc n clasa
publisher sau n afara oricrei clase, pentru c este o declarare de tip.
t Evenimentul i handler-e le de evenimente trebuie s aib o semntur i
un tip de retur identice.
110 P artea I. L im bajul C#

2. Declar evenimentul. Evenimentul se declar ca membru public n clasa


publisher, cu ajutorul cuvntului cheie event,. El depoziteaz i invoc
lista de hartdler-e.
3. Scrie cod care declaneaz evenimentul. Codul se scrie n clasa
publisher. Apelarea evenimentului duce la invocarea tuturor metodelor
handler nregistrate cu acest eveniment.
4. Declar event handler-e\e. Se declar n clasele subscriber i sunt
metode (event handier-e) care se execut cnd evenimentul se
declaneaz.
5. nregistrareaz handler-ele. Aceasta presupune conectarea
evenimentului la metodele handler. Codul se scrie n clasele subscriber
sau n alte clase, dar nu n publisher.
Este important de reinut c prin mecanismul de semnalare i de tratare a
evenimentelor, se realizeaz o decuplare a obiectelor de tip publisher de obiectele
de tip subscriber. Clasa publisher nu tie nimic despre obiectele sau clasele
subscriber care vor fi notificate.
Programul care urmeaz, declar tipul delegat Timp. Metodele handler
trebuie s potriveasc acestui tip, adic s nu aib parametri formali i tipul de
retur s fie void. Clasa Publisher (evident, poate fi oricare alt nume), declar
evenimentul ca i cmp public cu numele eveniment, de tipul Timp. Metoda 1= 1 j,.
Declanseaza() declaneaz evenimentul prin apelul eveniment!). De f a p t . ' S f
evenimentul ca atare este trecerea a 3 secunde, iar eveniment/) declaneaz
apelul metodelor handler din lista de invocare a evenimentului. Programul declar j
dou clase subscriber, A i B, care definesc cte o metod de tratare a
evenimentului care se semnaleaz n clasa Subscriber. nregistrarea handler-
elor are loc n Main (), dar s-ar fi putut face i n metode ale claselor subscriber.

II event.cs
using System;

public delegate void Timp(); // Declararea tipului delegat

// Publisher nu stie nimic despre obiectele pe care le va


// notifica sau despre metodele inregistrate evenimentului
public class Publisher
{
public event Timp eveniment; // Declararea evenimentului

public void Declanseaza()


{
while (true)
1
// Execuia programului se ntrerupe 3 secunde
S y s t e m .Threading.Thread.S l e e p (3000);

// Ne asigurm c exist metode nregistrate


if (eveniment != nuli)
eveniment(); // Declaneaz evenimentul
C apitolul 5. T rsturi eseniale ale lim bajului CU 111

} / / o dat la trei secunde


)
)

// Clase Subscriber
class A
{
public void HandlerA()
1
Console.WriteLine("Obiect A, notificat la {0}",
DateTime.Now);
}
)

class B
{
public void HandlerB()
1
Console.WriteLine("Obiect B, notificat la {0}",
DateTime.Now);
>
}

class Test
{
static void Main()
{
Publisher p = new Publisher();
// Obiectele a si b vor fi notificate la declanarea
// unui eveniment
A a = new A ();
B b = new B ();

// Clasele A i B subscriu acestui eveniment


p.sveniment += a.HandlerA; // nregistrarea metodelor
p.eveniment += b.HandlerB; // h a n d l e r

// Apeleaz metoda care declaneaz evenimentul


p .Declanseaza();
1
)

Programul afieaz la fiecare trei secunde, cte dou linii:

Obiect A, notificat la 12.06.2008 10:13:22


Obiect B, notificat la 12.06.2008 10:13:22
Obiect A, notificat la 12.06.2008 10:13:25
Obiect B, notificat la 12.06.2008 10:13:25
112 P artea I. L im bajul C#

Pentru determinarea datei i a orei curente, se utilizeat proprietatea Now, a clasei


System.DateTime.

IMPORTANT________________________
nregistrarea metodelor ataate unui eveniment se face cu operatorul +=,
iar ndeprtarea lo r din lista de invocare, se face cu -= .

Publicarea evenimentelor n mod specific .NET

Tratarea evenimentelor presupune existena unui tip delegat. Acesta poate fi


creat de dumneavoastr, ns o mai bun alternativ este folosirea tipului delegat
predefinit al platformei .NET.

Cnd evenimentul nu transmite date handler-elor


public
delegate void EventHandler(object s e n d e r , EventArgs e ) ;

s e n d e r este o referin la obiectul (de tip publisher) care declaneaz


evenimentul, iar e este o referin la un obiect de tip EventArgs. Declararea de
mai sus nu trebuie fcut n program, pentru c o face platforma .NET. Ceea ce
avei de fcut n programul events.cs, este s tergei linia care declar tipul
delegat Timp i s v declarai un eveniment n clasa Publisher, astfel:

public event EventHandler eveniment;

Handler-ele trebuie s aib desigur, aceeai semntur i tip de retur, cu a tipului


EventHandler:

public void HandlerA(object s e n d e r , EventArgs e)


i
public void HandlerB(object s e n d e r , EventArgs e)

O ultim modificare pe care o facei, este nlocuirea apelului eveniment ( ) ; cu


apelul eveniment (this, new EventArgs ());

Cnd evenimentul transmite date handler-elor


Obiectul de tip EventArgs nu conine n realitate date utile i este folosit
atunci cnd un eveniment nu transmite date de stare unui event handler. Dac
dorii s transmitei handler-e lor informaii suplimentare despre eveniment, putei
crea o clas, de exemplu MyEventArgs, care menine aceste informaii. Aceast
clas trebuie s fie derivat (s moteneasc) clasa EventHandler, aa cum se
vede n programul care urmeaz. n aceast situaie, vei crea un tip delegat cu o
semntur compatibil .NET. Vom rescrie programul anterior. Tipul delegat se va
declara ca mai jos:
C apitolul 5. Trsturi eseniale ale lim b a ju lu i C# 113

public delegate void T i m p (object s e n d e r , MyEventArgs ev);

s e n d e r este o referin la object, deci poate referi obiecte de orice tip, inclusiv
Publisher. n apelul eveniment (this, ev) ; argumentele sunt: referina this
la obiectul de tip Publisher i referina ev la un obiect de tip MyEventArgs.

using System;

public class MyEventArgs : EventArgs


{
private DateTime momentul; // Cmp
public DateTime Momentul // Proprietate
{
set
{
momentul = value;
}
get
{
return thi s .momentul;
}
1
}

// Declar tipul delegat cu prototipul cerut de .Net


public delegate void T i m p (object sender, MyEventArgs e v ) ;

public class Publisher


{
public event Timp eveniment; // Declar evenimentul

public void Declanseaza()


{
while (true)
{
// Execuia programului se ntrerupe 3 secunde
System.Threading.Thread.Sleep(3000);
if (eveniment != null) // Ne asigurm ca exist
{ // metode nregistrate
MyEventArgs ev = new MyEventArgs();
ev.Momentul = DateTime.Now;
// Declaneaz invocarea h a n d l e r - e lor
eveniment(this, e v ) ;
}
}
)
>

// Clase S u b s c r i b e r
114 P artea I. L im bajul C#

class A
1
public void HandlerA(object sender, MyEventArgs e)
{
Console.WriteLine{"Obiect A, notificat la (0}",
e .Momentul) ;
}
)

class B
{
public void HandlerB(object sender, MyEventArgs e)
{
Console.WriteLine("Obiect B, notificat la {0}",
e.Momentul) ;
}
}

class Test
{
static void Main()
{
Publisher m = new Publisher();
A a = new A(); // Obiectele a si b vor fi notificate
B b = new B(); // la apariia evenimentului

// nregistrarea metodelor handler


m.eveniment += a.HandlerA;
m.eveniment += b.HandlerB;

m.Declanseaza();
}
}

Ieirea programului este identic cu cea a programului anterior.

De retinut:

Dac vrei s scriei cod eficient, vei trata evenimentele folosind clasele de
baz E ve n tH a n d le r i E ventA rgs, iar delegrile vor avea prototipul compatibil
.NET, chiar dac C# admite orice model delegat.

G enerice

P rogram area G eneric sau programarea cu abloane este un stil de


programare diferit de Programarea Orientat pe Obiecte. Au n comun
abstractizarea datelor i reutilizarea codului, dar abordrile sunt diferite. n timp ce
C apitolul 5. Trsturi eseniale ale lim baju lui CU 115

OOP ncapsuleaz n acelai obiect date care reflect starea obiectului, mpreun
cu metode care descriu capabilitile lui, scopul programrii generice este scrierea
de cod care s fie independent de tipurile de date.

Clase generice

S presupunem c ai definit o clas stiva ca mai jos:

public class Stiva


{
private int{] a;
private int n;

public Stiva(int max)


{ a = new int[max]; }

public void Push(int val)


{ a[n++] = val; }

public int P o p ()
{ return a[ n]; }
}

Acesta stiv memoreaz n cmpul a de tip tablou de int, un numr de valori


ntregi. Dac dorii s depozitai valori de tip double, string sau oricare alt tip,
suntei nevoii s rescriei codul, nlocuind tipul int cu noul tip. C# v ofer
posibilitatea s scriei doar o singur definiie de clas, care s lucreze cu toate
tipurile dorite. Vei scrie o clas generic.
Clasele generice sunt tip u ri param etrizate. Clasa generic se va numi
Stiva<T> i se va rescrie astfel:

// stiva_generic.cs
using System;

public class Stiva<T>


{
private T[] a;
private int n;
public Stiva(int max) // Constructor
{ a = new T[max]; )
public void Push(T val)
{ a[n++] = val; }
public T P o p ()
{ return a[ n] ; }
}
116 P artea I. L im bajul C#

public class TestGeneric


{
static void Main()
{
// Se creeaz o stiv de int (T = int)
Stiva<int> sl = new Stiva<int>(100);
s l .P u s h (2);
sl.Push(4);
s l .Push (6);
Console.WriteLine (sl.PopO + " " + s l . P o p O + " " +
sl.PopO);
// Se creeaz o stiv de string (T = string)
Stiva<string> s2 = new Stiva<string>(50);
s 2 .Push("Marcel");
s2.Push("Ionel");
s 2 .P u s h ("Alin");
Console.WriteLine(s2.P o p () + " " + s2.Pop() + " " +
s2 .Pop () ) ;
}
}

Ieire:
6 4 2
Alin Ionel Marcel

Numele clasei generice este Stiva<T>. De fapt, nu este o clas real, ci


este un ablon de clas. Pe baza ablonului de clas se vor genera clase reale,
pentru valori particulare ale parametrului T.
Parametrul ablonului este T. Se numete param etru tip sau parametru
generic.
Expresia Stiva<int> sl = new Stiva<int> (100) ; creeaz pe
baza ablonului stiva<T> o clas cu numele stiva<int>, apoi instaniaz un
obiect de acest tip, deci o stiv de ntregi.
Argumentele cu care se nlocuiesc param etrii tip se numesc argumente
tip. Mai sus, T este parametru tip, iar int este argumentul tip.
O clas poate avea mai muli parametri generici. Programul urmtor declar
o clasa generic (nu uitai, o clas generic este un ablon de clas), cu doi
parametri tip, Tl i T2:

using System;

public class A < T 1 , T2>


{
private Tl a;
private T2 b;
public A(Tl a, T2 b) // Constructor
{
this.a = a;
this.b = b;
}
C apitolul 5. Trsturi eseniale ale lim bajului C # 117

public void Prin()


{
Console.Writeline(a + " " + b) ;
}

public class TestGeneric


{
static void Main() .
{
A<string, int> ml = new A<string, int>("Alin", 18);
m l .P r i n ();
A<string, string> m2 = new A<string, s tring>("UNU",
"DOI");
m 2 .P r i n ();
A<double, char> m3 = new A<double, c h a r > (2.3, 1F 1);
m3 .P r i n ();
)
}

Ieire:
Alin 18
1 2
2.3 F

Expresia A<string, int> ml = new A<string, int>("Alin", 18);


genereaz pe baza ablonului A < T 1 , T2> o clas cu numele A<string, int>,
apoi instaniaz un obiect ml de acest tip. Similar se genereaz i celelalte clase,
respectiv obiecte. n felul acesta, metoda Prin () a primit o funcionalitate
extins.

Metode generice

Toate metodele unei clase generice sunt la rndul lor generice, deoarece pot
utiliza parametrii generici ai clasei. n afara genericitii implicite, putei defini
metode cu proprii parametri generici, care nu depind de cei ai clasei.

Exemplu:
using System;

public class C<U>


{
private U u;

public C (U u) // Constructor generic


{
118 P artea I. L im bajul C#

this.u = u;
1
// Metoda generic - are proprii parametri generici
public void F<V1, V2><V1 a, V2 b)
{
Co n s o l e .WriteLine(a.ToString() + " " + u . T oStringO +
" " + b.ToString());
}
}

public class TestMetodaGenerica


{
static void Main()
{
C<int> cl = new C<int>(104); // U = int
cl.F<string, string>("Sa traiti", "ani!");

C<char> c2 = new C<c h a r > ('F '); // U = char


c2.F<string, i n t > ("Iulia", 8) ;
}
>

Ieire:
S traiti 104 ani!
Iulia F 8

Expresia c<int> cl = new c<int> (104); genereaz clasa c<int> pe baza


ablonului de clas C<T>.
Expresia cl.F<string, string>("Sa traiti", "ani!"); genereaz
metoda F<string, string>() pe baza ablonului de metod F< v i , V2>(V1
a, V2 b ) , apoi apeleaz metoda cu dou argumente de tip string. Metodele cu
proprii parametri generici i sporesc funcionalitatea n raport cu celelalate metode
ale unei clase ablon.

Avantajele programrii generice


Acest model de programare permite implementarea algoritmilor generici.
Pentru asemenea algoritmi, datele se manipuleaz n acelai fel ca n cazul
algorimilor non-generici, n timp ce tipurile de date utilizate pot s fie schimbate de
ctre programator dup necesiti. Genericele se remarc prin calitatea i elegana
codului, sintaxa uor de neles. Codul se poate reduce semnificativ ca volum
atunci cnd avei sarcini de programare cu cod repetabil.
Folosirea tipurilor generice este recomandat de asemenea pentru sigurana
tipurilor care se creeaz (corectitudinea tipurilor se verific n timpul compilrii),
pentru performana n timpul rulrii i nu n ultimul rnd pentru creterea
productivitii n programare.
****

C apitolul 5. Trsturi eseniale a le lim bajului C# 119

C olecii
t
Platforma .Net conine clase specializate pentru depozitarea datelor.
Aceste clase implementeaz stive, cozi, liste, tabele de dispersie (hash-tables).
Coleciile non-generice sunt definite n spaiul de nume System.Collections.
Coleciile generice se definesc n System.Collections.Generic.
'^ ^ 'r f - j n w * "''

Cele dou tipuri de colecii implementeaz aproximativ aceleai tipuri de


structuri de date, ns cele generice sunt mai performante i furnizeaz o mai mare
siguran a tipurilor. Prezentm modul de utilizare a ctorva containere generice.

Clasa generic stack<T>


^

s t a c k < T > este o colecie de instane de acelai tip t , care implementeaz


r r n ii-uiiyqip ffm T im O T w rT -tn irn -r^ rirT ^ ^ ^ -^ T ^ r T^

operaii specifice unei stive (U FO ). Managementul memoriei se face automat.


Exem plu:

using System;
using System.Collections. Generic;

class StivaGenerica
1
public static void Main()
{
// Declar o stiv vid cu elemente de tip string
Stack<string> st = new Stack<string>();

// Adaug cteva elemente n stiv


s t .P u s h (" U N U " ); s t .P u s h ( " D O I " );
s t . P u s h ( " T R E I " ) ; s t .P u s h (" P A T R U " );
Console.WriteLine("Nr. de elemente: {0}", st.Count);

foreach (string s in st) // Se parcurge stiva


Console.WriteLine(s);
ww'ii^ tiy

// Pop () scoate elementul din vrful stivei


Console.WriteLine ("Scoate {0}', s t . P o p O ) ;

// Peek) returneaz elementul din vrful stivei


// fr s-l scoat din stiv
Console.WriteLine("Vrful stivei: {0}", st.Peek());
st.Clear(); // terge toate elementele
>
}

Ieire:
N r . de elemente: 4
PATRU
jiHfWM'Oi

TREI
120 P artea I. L im bajul C #

DOI
UNU
Scoate 'PATRU'
Vrful stivei: 3

Clasa generic L is t< T >

Ciasa reprezint o list de obiecte care poate fi accesat prin index.


Implementeaz metode pentru cutarea, sortarea i manipularea obiectelor. Este
echivalentul clasei non-generice ArrayList, dar mai performant dect aceasta.
E x e m p lu :

using System;
using System.Collections.Generic;

public class ListaGenerica


{
public static void Main()
{
// Creeaz lista copii cu elemente de tip string
List<string> copii = new List<string>();

// Adaug elemente n list


copii.Add("Ionel"); copii.Add("Radu");
copii.Add("Viorel"); copii.Add("Adisor");
c o p i i .A d d ("Nelutu");

// Parcurge colecia
foreach (string c in copii)
Console.Write(c + " " );
Console.WriteLine("\nNr. copii: (0)", copii.Count);

// Contains() returneaz true dac un element exist


Console.WriteLine("Viorel exista ? {0}\n",
copii.Contains("Viorel"));

Console.WriteLine("Insereaz V ' A l i n V " +


"pe poziia 2 : ;
c o p i i .I nsert(2, "Alin");

foreach (string c in copii)


Console.Write(c + " ");
Console.WriteLine(\ncopii[3] = {0}", copii[3]);

Console.WriteLine("XnSorteaza alfabetic: ");


c o p i i .S o r t ();
for (int i = 0; i < copii.Count; i++ )
Console.Write(copii[i] + " ");
Capitolul 5. T rsturi eseniale ale lim b a ju lu i C # 121

Console.WriteLine("\n\nSterge \"Nelutu\":");
copii.R e m o v e ("Nelutu");

foreach (string c in copii)


Console.W r i t e (c + "

C o n s o l e . WriteLine("\n\nSterge lista de copii:");


copii.C l e a r ();
Console.WriteLine(" N r . copii: {0}", copii.Count);
}
)

Ieire:
Ionel Radu Viorel Adisor Nelutu
Nr. copii: 5
Viorel exista ? true

Insereaz "Alin" pe poziia 2:


Ionel Radul Alin Viorel Adisor Nelutu
copii[3] = Viorel

Sorteaza alfabetic:
Adisor Alin Ionel Nelutu Radu Viorel

terge "Nelutu :
Adisor Alin Ionel Radu Viorel

terge lista de copii:


N r . de co p i : 0

Clasa generic DictionaryCTkey, Tvalue>

Clasa este echivalentul clasei map din STL, C++. Realizeaz o mapare, o
coresponden biunivoc ntre o mulime de chei i o mulime de valori. Cheile sunt
unice, n sensul c nu pot exista mai multe chei identice n dicionar. Fiecrei chei i
corespunde o singur valoare asociat.
Clasa ofer metode care implementeaz operaii rapide de inserare a
perechilor cheie-valoare, de tergere i de cutare a valorii dup cheia asociat. n
dicionar, perechile cheie-valoare sunt ncapsulate n obiecte de tip
KeyValuePair.

Exemplu:

uslng System;
using System.Collections.Generic;
122 P artea I. L im bajul C#

public class AgendaTelefonica


{
public static void Main()
1
/ / U n dicionar cu cheia string i valoarea int
Dictionary<string, int> T =
new Dictionary<string, i n t > ( ) ;
// Adaug elemente in dicionar.
T.Add("Ionescu", 209791); // Insereaz cu Add()
T.Add("Pop", 232145);
T["Vlad"] = 213048; // Insereaz cu operatorul
T ["Cazacu"]= 219465; // de indexare

Console.WriteLine("Cheia Vlad are valoarea: {0}",


T ["Vlad"]);

// Cu operatorul de indexare poate schimba valoarea


// asociat unei chei existente
T ["Vlad"] = 215773;
Console.WriteLine("Cheia Vlad are valoarea: (0)\n",
T ["Vlad"]);

// Dac cheia nu exist in dicionar, se adaug o


// nou pereche cheie-valoare
T ["Dragnea"] = 279950;

// ContainsKey() se folosete pentru a testa


// existena unei chei nainte de inserare
// if (!T.ContainsKey("Simion"))
T .A d d ("Simion", 200371);

// In dicionar elementele se memoreaz ca perechi


// cheie-valoare n obiecte de tip KeyValuePair
foreach (KeyValuePair<string, int> p in T)
Console.WriteLine("(0, -7} (1, 10}",
p.Key, p.Value);

// terge o pereche cheie-valoare


T.Remove("Ionescu");
if ( !T.ContainsKey("Ionescu) )
Console.WriteLine("\nCheia Ionescu nu exista");
}
}

Ieire:
Cheia Vlad are valoarea: 213048
Cheia Vlad are valoarea: 215773
C apitolul 5. T rsturi eseniale ale lim b a ju lu i C# 123

Ionescu 209791
Pop 232145
Vlad 215773
Cazacu 219465
Dragnea 279950
Simion 200371

Cheia Ionescu nu exista

Tratarea ex ce p iilo r

n timpul execuiei unui program pot aprea situaii excepionale, cum ar fi


operaii ilegale executate de propriul cod, care pot duce la ntreruperea execuiei
programului sau la un comportament neateptat. Aceste situaii se numesc
excepii. C# ofer un mecanism de tratare a excepiilor, bazat pe cuvintele cheie
try, catch i finally.
Erorile din timpul rulrii programului se propag n program cu ajutorul
acestui mecanism de tratare a excepiilor. Vei include codul care este probabil s
arunce excepii, ntr-un bloc try. Cnd excepia se produce, fluxul de execuie al
programului este dirijat direct n blocul de cod numit catch, care prinde" i
trateaz excepia. Excepiile neprinse, sunt captate de ctre un h andler furnizat
de ctre sistem, care afieaz un mesaj de eroare.
Tipurile execepiilor care pot s apar sunt reprezentate de ctre clase
specializate ale platformei .NET, clase care deriv din clasa Exception.

Pentru tratarea excepiilor, vei proceda astfel:

try
{
// Cod care poate arunca excepii
1
catch(System.Execption e)
{
// Cod care trateaz excepia
1
finally
{
// Cod care se execut dup try-catch indiferent
// dac se arunc sau nu execepii

Exemplu:

using System;

class TestExceptii
jjfe
I P artea I. L im bajul C#
124

public static void Main()


{
int [ ] a = { 2, 4, 6, 8 };
try

Console.WriteLine(a[4]);

catch (Exception e)

Console.WriteLine("Excepie !\n" + e .ToSt r i n g ());


1
finally
t-
*
Console.WriteLine(a[3]);

>

Ieire:
Excepie!
System.IndexOutOfRangeException: Index was outside the bounds
of the array at TestExceptii.Main() in c:\teste\Program.cs:
line 7

i
Blocul catch declar o variabil de tip execpie (e) care poate fi utilizat pentru a
obine informaii suplimentare. Codul din blocul finally se execut indiferent
dac se arunc sau nu o excepie n blocul try, permind programului s
fj-T elibereze resursele (fiiere deschise, memorie alocat, etc.). Dac excepia se
ul
produce, atunci blocul finally se execut dup catch. &
iii Blocul finally poate s lipseasc. Pentru acelai bloc try, se pot declara mai
Ts-
it
multe blocuri catch, fiecare dintre ele, preciznd o posibil excepie care se poate I
lansa din try.
4 Hi

M anevrarea strin g u rilo r

Tipul string n C# este un alias pentru clasa System, string din .Net
Framework. Este un tip referin. Obiectele de tip string ncapsuleaz un ir de
caractere n format Unicode. Stringurile sunt imutabile. Odat creat, un obiect de
tip string nu mai poate fi schimbat; toate operaiile care modific un string
returneaz un alt string modificat.

ii-
ini
0:-
C apitolul 5. Trsturi eseniale ale lim bajului C# 125

Operaii i metode
string definete operatorii relaionali =, != i operatorii de concatenare +,
+=. Definete de asemenea mai muite metode utile. Vom exemplifica utilizarea
ctorva dintre ele.

using System;

class TestString
{
public static void Main()
{
string sl = "Salut", s2 = "salut ;
if (sl != s2) // Compar stringurile, nu obiectele
Console.WriteLine("sl != s2") ;
if ( sl.ToUpper) = s2.ToUpper() )
Console.WriteLine(sl.ToUpper()); //Afieaz SALUT

sl += s2; // sl este acum "Salutsalut"


// Insereaz irul " " ncepnd cu poziia 5
string s = sl.Insert(5, " "); // sl nu se modific!
Console.WriteLine(s); // Afieaz: "Salut salut"

// Extrage din s, ncepnd cu poziia 6,


// un substring format din 3 caractere
s = s.Substring(6, 3);
Console.WriteLine(s); // Afieaz: "Salut salut"
}
}

Formatarea stringurilor
Pentru formatarea stringurilor exist n clasa string metodele statice
Format (), suprancrcate.

Exem plu:

using System;
class TestString
1
public static void Main()
x
int x = 123; double y = 23.4589;
string s = String.Format("x = {0}, y = {1}", x, y) ;
Console.WriteLine(s); // Afieaz: 123 23.4589
}
}

Mai sus, { 0 } se refer la primul obiect (x) din lista de parametri, iar { 1 } identific
cel de-al doilea obiect (y).
126 P artea I. L im bajul C#

Opiunile de formatare sunt diverse. Putei stabili aliniere ju s tify la stnga


sau la dreapta i formatul de afiare a numerelor:

E x e m p lu :

float x = 123.3456F; double y = 23.4589; string s;


s = String.Format("x = {0,12:E3}\ny = {1,12:F2}", x, y) ;
Console.WriteLine(s);

Afieaz:
x = 1.233E+002
y = 23.46

Specificatorul { 0, 1 2 : E 3 } se interpreteaz astfel: 0 - identific primul obiect


(x), 12 este limea cmpului de afiare, E cere afiare n format tiinific, iar 3 este
numrul de zecimale care se afieaz.
Specificatorul {1,12 :F2} se interpreteaz astfel: 1 - identific al doilea
obiect (y), 12 este limea cmpului de afiare, F impune afiare n virgul fix, iar
2 este numrul de zecimale care se afieaz. Dac dorii aliniere la stnga, se
pune semnul - dup virgul: {1,-12:F2}.
Stringurile se pot formata pentru afiare dup aceleai reguli i cu ajutorul
metodelor Console .Write {) i Console .WriteLine ( ) :

E x e m p lu :

double x = 23.4589;
Console.WriteLine("|x = {0,10:F2}|", x) ;
Console.WriteLine("|x = {0,-10:F 2 } |", x ) ;

A fi e a z :
|x = 23.461
|x = 23.46 |

Transformarea stringurilor n valori numerice

n C# nu exist metode sau operatori care s citeasc date numerice din


stream-uri i s le formateze direct n valori numerice, aa cum sunt funciile
scanf () din limbajul C, sau operatoul de extracie din C++. De regul, vei citi
datele ca stringuri. Din aceste stringuri, vei extrage valorile numerice.
Tipurile predefinite (int, double, float, etc.) definesc metoda Parsef).
Aceasta preia stringul citit i l transform n valoarea numeric corespunztoare.

E x e m p lu :

int n = i n t .P a r s e ("652"); // n = 652


double d = d o u b l e .P a r s e ("-20.235"); // d = -20.235
C apitolul 5. T rsturi eseniale ale lim bajului C# 127

// Citim un numr real de la tastatur:


string s = Console.ReadLine(); // s = "91.045"
double f = d o u b l e .P a rse(s); // f = 91.045

Citirea unui ir de valori numerice


Dac este nevoie s citii un ir de valori numerice dintr-un stream, de
exemplu de la tastatur, atunci trebuie s precizai caracterul sau caracterele
separatoare ntre numere.
Un caz simplu este acela n care toate numerele sunt desprite printr-un
singur spaiu i se gsesc pe o singur linie. Se citete linia ntr-un string, apoi se
desparte stringul n substringuri reprezentnd numerele. Pentru aceasta, utilizai
metoda Split(). Aceasta returneaz un tablou de stringuri reprezentnd
numerele citite.

E x e m p lu :

string linie = Console.ReadLine();


string[] s = linie.Split(' '); // Separatorul este
int x; // caracterul spaiu
foreach (string nr in s) // Parcurge tabloul de stringuri

x = int.Parse(nr); // Le transform n valori int


Console.Write(x + " ");

Metoda split() este suprancrcat. Una dintre versiuni are ca parametru


un ir de caractere char[], n acest ir vei introduce toate caracterele
separatoare pe care le considerai necesare. Al doilea parametru al metodei, v
permite s nlturai toate substringurile vide din tabloul de stringuri rezultat n
urma splitrii. Se obin stringuri vide n situaia cnd n stringul iniial apar doi sau
mai muli separatori consecutivi.

E x e m p lu :

using System;
public class TestSplit

static void Main()


{
c h a r [] sep = { 1\ n ' , ' ', '.', ' ! 1 } ;
string s = "12 2 7 \ n . .. 496!";
string[] w = nuli;
// Tabloul w preia substringurile fr separatori din s
w = s .S p l i t ( s e p , S t r i n g S p l i t O p t i o n s .R e m o v e E m p t y E n t r i e s );

for (int i = 0; i < w.Length; i++)


{
int x = int.Parse (w[i]);
128 P artea I. L im bajul C#

Console.Write(w[i] +
}
}
}

Ieire:
12_27_496_
Cunosctorii limbajului C au remarcat desigur similitudinea ntre metoda Split ()
i funcia strtok ().

Citiri i a fi ri din fiiere de tip text

Toate intrrile i ieirile n C#, la fel ca n C++ sau Java, presupun folosirea
stream-urilor. Un stream este o reprezentare abstract a unui dispozitiv fizic
(memorie, fiier, reea, etc.), n care informaia se poate accesa doar cte un byte
odat. ntr-un stream informaia circul ntr-un singur sens. De exemplu, un
program nu va scrie datele direct ntr-un fiier, ci le va scrie ntr-un stream de ieire
care reprezint fiierul.
Exist stream-uri de intrare i stream-uri de ieire. Din stream-urile de intrare
programul citete date, iar n cele de ieire scrie date. Pstrnd dispozitivul n
form abstract, destinaia sau sursa stream-ului poate fi ascuns. Aceasta
permite reutilizarea codului, iar codul este similar atunci cnd aplicaiile scriu sau
citesc din fiiere sau din reea, de pe disc, din memorie, sau din oricare alt
dispozitiv.
.NET Framework definete n spaiul de nume S ystem .lO acele clase care
reprezint stream-uri cu fiiere. Sunt mai multe astfel de clase. n acest paragraf ne
referim la doar un singur aspect: citirea i scrierea datelor numerice din fiiere text.
lat un program pentru exemplificare:

using System;
using System.lO;

class FileReadWrite
{
static void Main()
{

string fin = @ " C :\teste\nume.re.in" ;


string fout = @"C:\teste\numere.out";

// Deschide fiierele de intrare i de ieire


StreamReader sr = new StreamReader(fin);
StreamWriter sw = new StreamWriter(fout);

s tring[] s = nuli;
string linie = nuli;
C apitolul 5. T rsturi eseniale a le lim bajulu i C# 129

int x = 0;

// Citete cte o linie pn la ntlnirea


// sfritului de fiier
while ( (linie = sr.ReadLine()) != nuli )
(
s = linie.Split(' '); // Desparte linia in stringuri
foreach (string nr in s)
{
x = int.Parse(nr); // Obine valoarea numeric
s w .W r i t e ("{0, -5}", x ) ; // 0 scrie n fiier
}
sw.WriteLine();
}
sr.Close(); // nchide fiierele
sw.Close();
}
}

E xem plu : Dac nu m e r e .in conine valorile:

12 335 561
0 25 5 76
99 1 773 67 3

Atunci numere.out va avea:

12 335 561
0 25 5 76
99 1 773 67 3

Observaii:

> Clasele streamReader i streamWriter citesc, respectiv scriu caractere


din sfream-uri. Conin metodele ReadLine ( ) , respectiv WriteLine ( ) .
Acestea citesc sau scriu din stream pn la caracterul newtine.
> O constant ir de caractere se numete ir verbatim, dac se prefaeaz cu
caracterul Exemplu: @"C:\teste\numere.in". Efectul este c secvenele
escape din interior nu se mai evalueaz. Deci irul verbatim din exemplu este
echivalent cu C: \\teste\\numere.in".
> n expresia sw.Wri te (" { 0 , - 5 } " , x ) ;, 0 semnific primul obiect de afiat,
adic x, iar - 5 cere alinierea la stnga a rezultatului pe un cmp de lime 5.
> Dac fiierul de intrare poate avea ca separatori ntre dou numere pe aceeai
linie mai mult dect un singur spaiu, atunci vei folosi versiunea Split () cu
separatori, aa cum am artat n paragraful Transformarea stringurilor n
valori numerice.
130 P artea I. L im bajul C # C a p ito lu l 6. Aplicaii de tip Windows Forms
131

R ezu m a tu l c a p ito lu lu i Partea a II - a


O delegare este un tip referin, utilizat s ncapsuleze o list ordonat de
metode cu aceeai semntur i acelai tip de retur. Lista de metode se
numete lista de invocare. Cnd un delegat este invocat, el apeleaz toate Programare Windows
metodele din lista de invocare.
Evenimentele C# permit unei clase sau un obiect s notifice, s ntiineze cu Visual C# 2008 Express Edition
alte clase sau obiecte c ceva s-a ntmplat.
Un eveniment este un membru public al clasei care public evenimentul. C apitolul 6
Atunci cnd are loc o aciune, acest membru al clasei publisher se
activeaz, invocnd toate metodele care au subscris evenimentului.
Scopul programrii generice este scrierea de cod care s fie independent Aplicaii de tip Windows Forms
de tipurile de date.
Exist clase generice i metode generice. Clasele generice sunt tipuri
Visual C# 2008 Express Edition (VCSE) ofer suport pentru dezvoltarea
parametrizate. Parametrii lor se numesc param etri tip sau param etri urmtoarelor tipuri de aplicaii:
g e n e rici.
Coleciile sunt clase specializate pentru depozitarea datelor. Biblioteca Aplicaii Windows de tip Windows Forms.
.NET definete colecii generice i colecii non-generice. Aplicaii Windows de tip WPF ( Windows Presentation Foundation).
Coleciile implementeaz stive, cozi, liste, tabele de dispersie (hash- Aplicaii de tip consol.
tables). Aplicaii de tip bibliotec dinamic.
Tipurile predefinite (int, double, float, etc.) definesc metoda Par se ( ) .
Aceasta preia stringul citit i l transform n valoarea numeric Aplicaiile de tip Windows Forms i cele WFP faciliteaz prin designer-ele integrate
corespunztoare. dezvoltarea interfeelor grafice cu utilizatorul (user interface).
Clasele StreamReader i StreamWriter citesc, respectiv scriu
caractere din sfream-uri. Conin metodele Read L i n e ( ) , respectiv;
W r i t e L i n e (). Acestea citesc sau scriu din stream pn la caracterul; Aplicaii cu interfa grafic cu utilizatorul
newline.
Biblioteca .NET conine un numr mare de clase definite n spaiul de nume
S ystem .W indow s.F orm s, cum sunt: Button, TextBox, ComboBox, Label, etc.
n treb ri i exerciii Instanele acestor clase identific controalele Windqws. Controalele sunt elemente
de interfa grafic ale unei aplicaii Windows.
1. Ce rol ndeplinete un tip delegat ntr-un program ? Un programator hardcore poate s codeze cu ajutorul acestor clase o
aplicaie cu interfa grafic orict de complicat fr a utiliza mediul integrat, ns
2. Cum putei elimina o metod din lista de invocare a unei delegri ? munca este imens. Este de preferat s lsai Visual C# s genereze pentru voi
- acel cod necesar interfeei grafice, ca s v putei concentra pe funcionalitatea
3. De ce se spune c aplicaiile Windows sunt conduse de evenimente ? aplicaiei. Vei utiliza pentru aceasta W ind ow s F orm D e s ig n e r i Toolbox. Cu
mouse-ul, prin drag and drop vei alege controalele necesare din T o o lb o x i le vei
4. Evideniai asemnrile i deosebirile dintre tipul tablou i tipul List<T>. ; aranja pe suprafaa formelor n W in d o w s F orm D esigner. Vei seta proprietile
i controalelor. Pe msur ce facei toate acestea, designerul genereaz codul C#
; aferent, pe care l scrie n fiierul <nume>.designer.es, unde <nume> este
5. S se citeasc din fiierul text matrice.in elementele unui table* numele formei respective.
bidimensional de valori ntregi. S se afieze n fiierul m atrice.out ptrafi
Aadar, sunt trei etape importante n crearea unei aplicaii cu interfa
valorii fiecrui element al tabloului. ; grafic:
1. A dugarea co n tro a le lo r pe suprafaa formelor.
2. Setarea p ro p rie t ilo r in iia le ale c o n tro a le lo r din fereastra
P roperties.
3. S crierea ha nd le re lo r pentru evenimente.
132 Partea a II-a. P rogram are W indow s cu V isual C# E xpress Edition

R ealizarea u n ei a p lic aii sim ple de tip W indow s Fo rm s

Vom crea o aplicaie numit Salut, care are un singur buton plasat pe o
form. La apsarea lui, apare o fereastr sistem de tip MessageBox, care afieaz
un mesaj de salut. Urmai paii:

1. n meniul File, click New Project.

2. n fereastra New P roject, n panoul Tem plates, alegei W indow s Form s


A p p lic a tio n .

3. n cmpul Name, scriei S alut, apoi click OK.


n acest fel ai creat un nou proiect W in d o w s F orm s. Acum urmeaz:

4. Din T o o lb o x, tragei un buton pe suprafaa formei.

Salut- Microsoft Visual CU 2008 Express Edition


File Edit View Project Build Debug Data Format Tools W indow Help

; >'

Toolbox. ' : r/'


f (Toolbox. X .; Form l.cs [Design]*
? Window* Forms
* o C o m m o n Controls
3 Solution 'S a lu t 'd project)
; :: h * Pointer
i a .23 S a lu t
;; Button ii a n Properties
: 0 CheckBox " References

; f i C heckedtistBox 3 Fo rm l.cs
^ Form l.Designer.es
I r f Com boBox
.|U ^ Fo rm l.re sx
: ^ DateTimeFlcker
IP ; ^ Program .cs
I A Label -'III
Linklabe!

; u s tB o x

\ Listview

5. Click dreapta pe butonul cu eticheta buttonl. Alegei Properties din


meniul contextual.

6. In fereastra P roperties, schimbai valoarea proprietii T ext n Apasa.


C apitolul 6. A p licaii d e tip W indows F orm s 133

- y ..^ ,*<j F o rm !. [D e sig n ]*


! ffiiAUWlodow form*,*: b utton 1 System. Windows.Forms.
I^.Common ontroU ^ ^
'I4 I
j (*b) Button i I (none)
I 0 Checkflox I (none)

; $ 2 CheckedLlstSox (none)
No
I S ComboBox Apaja
Apes* .g
1 H w DafceTimePicker TextAAgn WddleCenter
; A Label [ TextrmageReU Overlay
; A LinkLabel I UseMnemonic True

j S 3 ListBox j UscVisudStyle! T ru e
UseWaitCursor False
I l y ListVlew
0 Nefvtvim
7. Urmeaz tratarea evenimentului C lick, pentru ca aplicaia s rspund
acestui eveniment. Avei dou variante:
a. Dublu click pe suprafaa butonului.
b. n fereastra P roperties, click pe iconul fulger", numit Events. Din
lista de evenimente la care poate rspunde butonul, selectai
evenimentul C lick i apsai Enter.
n ambele situaii se deschide E d ito ru l de Cod. Fiierul deschis este
F o r m l.c s , iar metoda nou creat este b u t t o n l _ c l i c k . Acesta este
handler-ui de eveniment. Va fi invocat n mod automat la click pe buton.

8. n corpul metodei, scriei codul:

private void buttonl_Click(object sender, EventArgs e)


I
MessageBox.Show("Salut lume!");
}

9. Compilai i rulai aplicaia cu F5.

iSaU-Forml **:[,j*buttonl_.CJd<ob)ee>
rjl u s i n g S y s te ;
; u sing S y s t e .C o lle c t io n s .G e n e r ic ;
j u sing Syste.C om ponentH odel;
! u sing S y s t e .D e c ;
; u s in g S y s c e r e .D r a w in g ;
! u s in g S y s t e . L in c i;
Fereastra
: u s in g S y s te .T e x t; aplicaiei
'- u s in g S y s te . l/livdous. Foetus;

{=] namespace S alu t


i<
fS p u b lic p a r t ia l c la s s F c c tn l ; T o vrn
j ( Message Box
p u b lic Form lO
j (
In itia lite C o n p o n e n c {)*

p r iv a t e v o id b u t t o n l_ C iic )c (o b je c t sendet '-erjt A iy s e)


{
H s s a g t S o x . Sh ow ( " S a l u t lum e 1 ;
)
134 Partea a II-a. Program are W indow s cu V isual C# E xpress Edition

Observaie:
>
Pentru afiarea mesajelor de informare se utilizeaz metoda static Show()
a clasei System. Windows .Forms .MessageBox.

Controale, p ro p rie t i i even im ente

Controale
Controalele sunt instane ale unor clase .NET definite n spaiul de nume
S yste m .W in d o w s.F o rm s. Marea majoritate a acestor clase deriv din clasa
Control, care definete funcionalitatea de baz a oricrui control. Aa se explic
faptul c unele proprieti i evenimente sunt comune tuturor controalelor. Clasele
de tip control sunt organizate ierarhic, pe baza releiei de motenire, aa cum se
vede din diagrama parial de mai jos:

F ig. 6.1 S tru ctu ra ie ra rh ic a controalelor .N E T

n mod evident, diagrama de mai sus este incomplet. Numrul de controale este
mult mai mare.

Proprieti
Proprietile sunt membri ai claselor din care fac parte. Ele definesc
caracteristicile controalelor, de pild culoarea, poziia, dimensiunile acestora.
Controalele motenesc proprietile claselor printe. n unele cazuri le suprascriu
(override), pentru a obine un comportament particular i definesc de asemenea
altele noi.
Fereastra P ro p e rtie s a mediului integrat este un instrument important.
Selectnd un control, avei acces vizual la proprietile i evenimentele pe care le
suport controlul. Controalele se creaz cu adevrat run-time, ns proprietile lor
iniieie pot fi stabilite design-time n aceast fereastr. Desigur c aceste
proprieti se pot modifica programatic n timpul execuiei programului.
C apitolul 6. A p licaii de tip W indows Form s 135

Evenimente
ncepnd cu aceast parte a lucrrii, ne vom preocupa doar de
evenimentele pe care le genereaz controalele Windows.

IMPORTANT
Programele cu interfa grafic cu utilizatorul sunt c o n d u s e de eve n im e n te
(event-driven)

n momentul n care utilizatorul acioneaz asupra unui control, cum ar fi


click pe un buton, sistemul de operare simte" i transmite controlului un mesaj.
Controlul genereaz atunci un eveniment specific acelei aciuni, ca un semn c
ceva s-a ntmplat. Programatorul poate s trateze sau nu acel eveniment. Dac
alege s o fac, atunci el trebuie s scrie o metod handler, aa cum este
b u t t o n l _ c l i c k () n paragraful anterior. Aceast metod se apeleaz n
momentul n care evenimentul are loc, iar codul ei asigur funcionalitatea dorit a
controlului.
Toate controalele au evenimente pe care le pot genera. Amintii-v c
evenimentele sunt membrii ai claselor de tip control definite de .NET.

Tratarea e v en im en telo r

n partea teoretic a lucrrii am discutat despre mecanismul tratrii


evenimentelor n C#. Un obiect public un eveniment, iar alte obiecte subscriu
acestui eveniment. Cnd evenimentul se declaneaz, toate obiectele care au
subscris sunt informate, n sensul c handlerele acestora se vor invoca.
S presupunem c avem o form, pe care ai aezat un buton. Vrem s
tratm evenimentul click pe buton. Cine este publisher ? Desigur, butonul. i cine
este subscriber ? Este fereastra printe, adic forma. Deci n clasa ataat formei
vom defini o metod handler. Cum are loc subscrierea ? Vom vedea cu exemplul
practic care urmeaz. Din fericire, codul necesar subscrierii i definiia metodei de
tratare a evenimentului se genereaz n mod automat, atunci cnd utilizai panoul
Properties.

Cum se creaz handler-ele

Pentru acelai control putei trata mai multe evenimente, definind desigur
cte un handler specific. Mai mult dect atat, un acelai handler poate fi utilizat
pentru mai multe controale, aa cum vom vedea n continuare.
Vom realiza un proiect cu trei controale de tipuri diferite. Pentru fiecare
control tratm evenimentul C lick. n mod evident, putem scrie cte un handler care
s rspund fiecrui control. Vom proceda ns altfel. Vom crea un singur handler
pentru C lick pe oricare control. Acest lucru este posibil, datorit signaturii speciale
a handlerelor .NET:
136 Partea a Il-a . Program are W indow s cu V isual C # E xpress E dition

private void N u m e H a n d l e r { o b j e c t sender, EventArgs e)


{
// Cod care trateaz evenimentul
}

s e n d e r este o referin la obiectul (controlul) care a generat evenimentul. Astfel, |


n corpul handlerului putem identifica acel control i putem trata n mod difereniat.

Aplicaia ClickEvent
Pentru realizarea proiectului, urmai paii de mai jos:

1. Creai un proiect de tip Windows Forms, cu numele C lickEvent.

2. Facei click drept pe suprafaa formei i alegei P roperties.

3. Schimbai (opional) titlul formei (implicit este F o rm l) n ClickEvent, J


modificnd valoarea proprietii Text. Modificai proprietatea Name la ( j l
valoarea FormaMea. Este noul nume al clasei formei. Numele implicit era g f :
F o rm l.
mi
4. (Opional). In S o lu tio n E x p lo re r facei click drept pe fiierul F o rm l.c s i --S -
redenumii-l FormaMea.cs. Dac fereastra S o lu tio n E x p lo re r nu e vizibil, ak
atunci din meniul View , alegei S o lu tio n E xplorer.

5. Tragei cu mouse-ul pe suprafaa formei din T o o lb o x trei controale diferite, :S


de exemplu un B u tto n , un C heckB ox i un T extB ox.

6. Selectai butonul i setai proprietatea T ext la valoarea Apasare, iar


proprietatea Name la valoarea buton (implicit aceasta era bu tto n l).

7. Selectai check box-ul i setai proprietatea Text la valoarea Validare, iar J


proprietatea Name la valoarea verif (implicit aceasta era checkB oxl).

8. Selectai csua de text i atribuii proprietii Name valoarea edit (implicit | j


aceasta era textB oxl).

9. Selectai butonul i din P roperties apsai butonul Events (fulgerul). Vei


crea un handler pentru tratarea evenimentului C lick generat de buton. |
Avei varianta simpl de a face dublu click pe eticheta Click din P roperties |L S
sau un simplu dublu click pe suprafaa butonului. n aceast variant se J|
genereaz metoda cu prototipul:

p r i v a t e v o i d b u t o n _ C l i c k ( o b j e c t sender, EventArgs e)

A doua variant este s dai alt nume metodei, din fereastra P roperties, I
editnd cmpul din dreapta etichetei Click. Putei pune de pild numele J t ^
e v e n im e n t_ C lic k , apoi apsai Enter.
C apitolul 6. A p licaii d e tip W indows F orm s 137

;': j3fe.AH Windows Form... ! I b u t o n System .Windows,Form*.Button


1 Common Control
i. [ ^ Pointer

8Ut0n S A ction
I evenim ent Cflekjj
, 0 CheckBox
( MouseCaotureChsng
! g CheckedLlstBox
M ouseC kk
< Combo6ox !S App^'ir.iiHi*
; T jg OrfeTimePictor ! PaW
; A tabel ,S Heh<VKir
\ A UnUabel CKangeUICues
ControiAdded
LtstSox
ControlRemoved
> } ! UstVtow
HdpRoquested
i i r MskedToxtBox Query AccesslbiStyHelp
; MonthClendar StyleChanged
Z i Notifylcon ! SystemCdorsCbanged

10. In E d ito ru l de Cod, completai corpul metodei generate, ca mai jos:

private void eveniment_Click(object s ender,EventArgs e)


{
Control c = (Control)sender; // Conversie explicit
// (downcast)
MessageBox.S h o w ("Ati fcut click pe controlul: " +
c.Name + " cu eticheta: " + c.Text);
}

11. Acum subscriem cu acelai handier, pentru evenimentele .generate de


C heckB ox i TextB ox. Selectai pe rnd cte unul dintre controale, i din
fereastra P roperties, apsai butonul Events, apoi alegei din lista din
dreapta etichetei Click acelai handler, eveniment Click.

f! ; v e r if System.Windows.Forms.CheckBox

'Sj.CJ#Ewitv _

a Action
A p a sa re 3,1
-----
MouseCaptureCharjeveniment_Click
MouseClick
j O validare A p p e ara n ce
Paint
B e h a v io r
C h a n g e U IC u e s
ControlAdded

12. Compilai i rulai cu F5 (sau click pe butonul cu iconul din b a ra de


in stru m e n te S tandard).
138 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress Edition

f A pasare j

0 validare Ati fcut click p e controlul; verif cu eticheta; yalidare

l OK j
I 'I

Observaii:
n corpul handlerului, c.Name i c.Text sunt proprieti ale controalelor,
reprezentnd numele obiectului care reprezint controlul, respectiv
eticheta afiat pe control. T extB ox nu are proprietatea Text.
Expresia Control c = (Control) sender; necesit o conversie
explicit (downcast), deoarece sender e de tip object, Control e
subclas pentru Object (sau object), iar conversiile implicite au loc
numai de la subclase la superclase.

O privire n spatele scenei

Ne referim la proiectul realizat n paragraful anterior. Am utilizat W indow s


F orm s D e s ig n e r care include ntre altele E d ito ru l de C od i fereastra P roperties,
pentru scrierea codului i tratarea evenimentul C lick. Pe msur ce operam n
mod vizual, mediul integrat lucra pentru noi, translatnd aciunile n cod C#. S
vedem:

A). Dup primul pas de creare a proiectului, aveam o form goal, cu eticheta
F o rm l. S-au generat fiierele de baz ale proiectului: Forml.cs,
Forml.Designer.es i Program.cs.

B). n urma plasrii controalelor pe form i a setrii proprietilor Name i Text


pentru form, buton, butonul de validare i controlul de tip TextBox, dar i a_
redenumirii fiierelor proiectului, n S o lu tio n E x p lo re r putei identifica:;
FormaMea.c s , FormaMea.Designer.cs, Program.cs.

Fiierul Program .cs

Fiierul conine metoda M a in ( ) . Este punctul de intrare n aplicaie. n


S o lu tio n E xp lo re r, facei click drept pe Program, cs i alegei View Code:
C apitolul 6. A plicaii de tip W indows F orm s 139

// fragment din codul Program.cs


static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormaMea());
1

Partea important este faptul c metoda Main() din clasa Program apeleaz
metoda Run ( ) .Run () e metod static a clasei Application. Run () lanseaz
n execuie aplicaia. O instan a clasei FormaMea este creat i este fcut
vizibil. n acest fiier ar trebui s nu modificai nimic.

Fiierul FormaMea.cs

Fiierul implementeaz n general constructorii clasei, i toate metodele


definite de programator.
n S o lu tio n E xplorer, facei click drept pe fiierul FormaMea.cs i alegei
View Code:

// fragment din codul FormaMea.cs


namespace ClickEvent
{
public parial class FormaMea : Form
{
public FormaMea()
{
InitializeComponent();
}
1

private void eveniment_Click(object sender, EventArgs e)


{
Control c = (Control)sender; // Conversie explicit
// (downcast)
MessageBox.Show ("Ati fcut click pe controlul: " +
c.Name + cu eticheta: " + c.Text);
1
)

Observaii:

Fierul definete clasa FormaMea. Cuvntul cheie parial spune faptul
c definiia clasei se va completa n alt fiier (FormaMea.Designer.cs).
FormaMea motenete clasa Form din .NET, pentru ca s aib toate
caracteristicile unei forme Windows.
Constructorul clasei, care se invoc la crearea formei, apeleaz metoda
InitializeComponent (). Aceast metod execut tot codul necesar la
140 Partea a Il-a . P rogram are W indow s cu V isu al C # E xpress E dition

iniializarea aplicaiei: crearea controalelor, setarea proprietilor iniiale,


etc. Cu alte cuvinte, tot ce ai setat design-time.
Practic, dumneavoastr vei coda mai mult n acest fiier. Este locul unde
definii de regul metode, proprieti i evenimente noi ale clasei.
Oricnd dorii ca o metod s fie apelat odat cu crearea formei, putei
alegei constructorul clasei n acest scop:

public FormaMea () // Constructor


{
// Aici putei apela metode.
// Controalele nu exist nc
InitializeComponent();
// Si aici putei apela metode.
// Forma i controalele sunt deja create
}

Cnd dorii ca un cod s fie executat ca rspuns la o aciune a user-ului,


vei identifica evenimentul care se declaneaz la aceaa aciune, i-l vei
trata. Vei scrie codul dorit n handler-ul de eveniment.

Fiierul FormaMea.Designer.es
Fiierul reine tot ce s-a stabilit n etapa de design, relativ la form i
controale. Codul fiierului se genereaz n mod automat.
n S o lu tio n E xplorer, facei click drept pe fiierul F o rm a M e a .D e s ig n e r.e s
i alegei View Code:

II fragment din codul FormaMea.Designer.es


namespace ClickEvent
{
parial class FormaMea
{
11 . . .
private void InitializeComponent()
{
II . . .
}
private System.Windows.Forms.Button buton;
private Sys t e m .W i n d o w s .F o rms.CheckBox v e r i f ;
private System.Windows.Forms.TextBox edit;
}
I

IMPORTANT! Fierul completeaz definiia clasei FormaMea reinnd


toate setrile fcute design-time.
IMPORTANT! Remarcm trei cmpuri private: referinele buton, verif i
edit. Cmpurile au aprut sub numele: buttonl, checkBoxl i
C apitolul 6. A plicaii d e tip W indows F orm s 141

textBoxl, n momentul n care ai plasat controalele pe form. Numele


actuale s-au generat automat, atunci cnd din fereastra P roperties ai
modificat proprietatea Name.
IMPORTANT! Cele trei referine sunt c o n in u te n clasa FormaMea.
Amintii-v relaia care se modeleaz la co n in e re : H AS A. ntradevr,
forma are un sau co n in e un buton, are un check box i are un text box.

Metoda InitializeComponentQ

Redm fragmentele semnificative de cod din acest metod:

private void InitializeComponent()

// Instanierea (crearea) celor trei controale


// prin apelul constructorilor
t h i s . b u t o n = n e w S y s t e m . W i n d o w s . F o r m s . B u t t o n ();
t h i s . v e r i f = n e w S y s t e m . W i n d o w s .F o r m s .C h e c k B o x ();
this.edit = n e w S y s t e m . W i n d o w s .F o r m s .T e x t B o x ();

// S e t a r e a p r o p r i e t i l o r i n i i a l e ale controlului
// b u t o n ca urmare a aciunilor de design n fereastra
// Properties i Form Designer.
this.buton.Location = new System.Drawing.Point(78, 23);
this.b u t o n .Name = "buton";
this.buton.Size = new System.Drawing.Size(75, 23);
this.b u t o n .Text = "Apasare";

// Subscrierea la evenimentul Click


this.b u t o n .Click
+= new System.EventHandler(this.eveniment_Click);

// Setri similare pentru celelalte dou controale


// . . .

// Adugarea controalelor pe form


this.Controls.Add(this.e d i t ) ;
th i s .Controls.Add(this.verif);
this.Controls.Add(this.buton);

// Setarea proprietilor formei


this.Name = "FormaMea";
t h i s .Text = "ClickEvent";

// Afiarea controalelor pe form


t h i s .ResumeLayout(false);
t h i s .PerformLayout();

Se impun cteva precizri cu privire la metoda lnitalizeComponent():


142 Partea a Il-a . P rogram are W indow s cu V isual C# E xpress Edition
C a p ito lu l 6. Aplicaii de tip Windows Forms 143
1. Codul metodei se genereaz n mod automat. N u e s te in d ic a t s 4. Din T o o lb o x , aducei pe form dou butoane.
m o d ific a i m a n u a l a c e s t c o d . Operai cu F orm D e sig n e r i fereastra
P ro p e rtie s i modificrile se produc de la sine.
5. Facei dublu click pe primul buton pentru a trata evenimentul C lic k . n
2. Metoda construiete controalele prin apelul constructorilor acestora.
E d ito ru l d e C o d , scriei n corpul handler-ului:
3. Metoda stabilete proprietile iniiale ale controalelor i ale formei.
4. Metoda stabilete subscrierea formei la evenimentele generate de ctre
private void buttonl_Click(object sender, EventArgs e)
controale. Subscrierea se face astfel: 1
// Declaneaz evenimentul Click pentru al doilea
this.buton.Click += new // buton
System.EventHandler(this.eveniment_Click); button2.Perf ormClick();
this.edit.Click += new }
System.EventHandler(this.eveniment_Click);
this.verif.Click += new
System.EventHandler(this.eveniment_Click); 6. Facei dublu click pe al doilea buton pentru a trata evenimentul C lic k . n
E d ito ru l d e C o d , scriei n corpul handler-ului:

this este referina la obiectul de tip FormaMea. 0 subscriere ca aceasta


private void button2_Click(object sender, EventArgs e)
este la fel de corect: {
MessageBox.Show("Ati fcut click butonul doi !");
buton.Click += eveniment_Click; 1
edit.Click += eveniment_Click;
verif.Click += eveniment_Click; 7. Apsai F5 pentru compilare i rulare.

Altfel spus, obiectul referit de this (forma) subscrie la evenimentele C lick ,


generate de ctre fiecare control, setnd pentru fiecare caz, acelai
h a n d le r: eveniment_Click.
5. Putei, cu siguran, s tratai un eveniment oarecare, scrind manual co d u l;
necesar subscrierii i definind un handler adecvat, fr utilizarea panoului 1
P ro p e rtie s . Totui, e mult mai comod s utilizai facilitile mediului)
integrat.
6. Ca idee general, numele fiierului <nume_form>.Designer.cs, ne 1
spune c este generat n ntregime de ctre compilator. n general, nu s e j
fac modificri manuale n acest fiier.

Declanarea programatic a unui eveniment


Mesajul se afieaz indiferent de butonul pe care facei click.

Putei constrnge programatic un control s genereze evenimentul C lic k l


chiar dac userul nu a acionat click pe acel control. Se utilizeaz metoda
PerformClick( ) . Vom face un mic proiect: 1 Crearea programatic a unui control
Aplicaia RaiseEvent
Pn n prezent, controaleielor prezente pe form le-au fost setate
proprietile design-tim e. Crearea lor are loc totui run-time, odat cu crearea
1. n meniul File, alegei NewProject.
formei. Putei utiliza oricare handler de eveniment pentru a crea i a seta proprieti
run-time pentru oricare control Windows.
2. n panoul T e m p la te s , selectai W indow s F o rm s A p p lic a tio n .

3. In cmpul Name, scriei de exemplu RaiseEvent ca nume de proiect.


144 P artea a II-a. Program are W indow s cu V isual C # E xpress E dition

Aplicaia DtpRuntime
Realizm o aplicaie care n timpul execuiei, prin apsarea unui buton, creaz
un nou control pe form, de exemplu un DateTimePicker. Un control
DateTimePicker afieaz data curent.

1. n meniul F ile , alegei N e w P ro je c t.


2. n panoul T e m p la te s , selectai W in d o w s F o rm s A p p lic a tio n .
3. In cmpul N a m e , scriei de exemplu DtpRuntime ca nume de proiect.
4. Din T o o lb o x , tragei pe form un buton.
5. Facei dublu click pe suprafaa butonului pentru a trata evenimentul C lic k ,
n E d ito ru i d e C o d , scriei n corpul handler-ului:

private void buttonl_Click(object sender, EventArgs e)


{
// Creaz runtime un obiect de tip D.T.P.
DateTimePicker dtp = new DateTimePicker();

// Location e poziia colului stnga sus al D.T.P.


dtp.Location = new Point(20, 20);

// Adaug controlul pe form


t h i s .Controls.Add(dtp);
C apitolul 7. C ontroalele W indows F orm s 145

C apitolul 7

Controalele Windows Forms


Exist o mare diversitate de controale predefinite .NET. ntr-o clasificare
relativ dup funcionalitate, distingem:

Controale pentru declanarea evenimentelor, cum este Button.


* Controale pentru editare de text, cum sunt TextBox sau RichTextBox.
* Controale pentru afiare de informaii pentru utlizator, cum sunt Labei i
LinkLabel.
Controale pentru afiare de liste, cum sunt Listview sau ListBox.
Controale pentru afiarea informaiilor din baze de date, cum este
DataGridView.
Controale de tip container, cum sunt GroupBox sau Panel.
Controale de tip meniu sau bar de instrumente, cum sunt MenuStrip
sau Tooistrip.

La cele de mai sus se mai adaug i alte tipuri de controale, care vor fi descrise n
cele ce urmeaz, nsoite de exemple practice.

Controlul Button
n spaiul de nume S ystem .W indow s.F orm s se definesc trei controale care
deriv din clasa ButtonBase: Button, CheckBox i RadioButton.
B u tto n este de departe cel mai comun control. Pentru a inspecta
proprietile i evenimentele unui buton, este suficient s creai rapid o aplicaie de
tip Windows Forms, s aducei pe form un buton i s parcurgei fereastra
P roperties. De multe ori ns nu este de ajuns pentru a v lmuri. De aceea, v
sftuim ca s avei mereu deschis Helpul mediului integrat i s v obinuii s
cutai rapid acolo oricare clas, proprietate sau cod exemplificator. Din meniul
Help, alegei C on tents. n panoul din stnga, expandai nodul .Net Fram ew ork
SDK. Apoi expandai .Net Fram ew ork C lass L ib ra ry. Expandnd mai departe
nodul S ystem .W ind ow s.F o rm s Nam espace, ntreaga galerie de clase de tip
control v este accesibil cu toate informaiile necesare.
Revenind la B utto n , acesta poate genera mai multe tipuri de evenimente,
ns n proporie covritoare, evenimentul C lick este cel mai folosit.

Aplicaia ButtonExample
Vom face o mic aplicaie care trateaz alte dou tipuri de evenimente i
pune n eviden cteva dintre proprietile butoanelor.

1. n meniul File, alegei N ew P roject.


146 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress E dition

2. n panoul T e m p la te s , selectai Windows Forms Application.

3. In cmpul N a m e , scriei de exemplu ButtonExample ca nume al


proiectului.

4. Din T o o lb o x , tragei cu mouse-ul pe suprafaa formei un control de tip


S p litC o n ta in e r . Acesta are aici rolul de a izola partea din stnga de cea
din dreapta a formei.

5. n panoul din stnga aducei un buton, iar n cel din dreapta, plasai dou
butoane.

8i
in
buttonl 42
ix ton

;'ij _____
v|: (button3 j

6. Acionai dublu click pe button 1 pentru a trata evenimentul C lick. n corpul


handlerului introducei codul:

private void buttonl_Click(object sender, EventArgs e)


(
// Dac butonul este andocat (umple panoul)
if (buttonl.Dock == DockStyle.Fill)
{
// l readucem la forma i eticheta iniiale
b u t t o n l .Dock = DockStyle.None;
b u t t o n l .Text = "buttonl";
i
else
{
/ / I andocm i schimbm eticheta
buttonl.Dock = DockStyle.Fill;
buttonl.Text = "Fill !!";
}
}

7. Selectai button2 i din fereastra P roperties setai proprietatea B a ckC o lo r


la valoarea Red. i proprietatea Text la valoarea Rosu.

8. Selectai button2, iar din fereastra P roperties, apsai butonul Events


(fulgerul). Facei dublu click pe evenimentul M ouseE nter. Acesta se
declaneaz atunci cnd mouse-ul intr pe suprafaa controlului. n corpul
handler-ului scriei codul:
C a p ito lu l 7. Controalele Windows Forms 147

private void button2_MouseEnter(object sender,


EventArgs e)
{ // Setm fundalul la culoarea galben
b u t t o n 2 .BackColor = C o l o r .Yellow;
b u t t o n 2 . T e x t = "Galben";
}

9. Selectai button2 i facei dublu click pe evenimentul M ouseLeave. Acesta


se declaneaz atunci cnd mouse-ul iese de pe suprafaa controlului. n
corpul handler-u\u\ scriei codul:

private void button2_MouseLeave(object sender,


EventArgs e)
{ // Resetm culoarea fundalului i textul
b u t t o n 2 .BackColor = Color.Red;
b u t t o n 2 .Text = "Rou";
}

10. Selectai button3 i din fereastra P roperties setai proprietatea T ext la


valoarea ieire.

11. Facei dublu click pe butonul cu eticheta Ieire, pentru a trata evenimentul
C lick. Introducei n corpul handlerului de eveniment, codul: .

private void button3_Click(object sender, EventArgs e)


{
Application.Exit(); // Ieire din aplicaie
}

12. Apsai pentru rulare F5, sau iconul ^ .

La click pe b u tto n l, acesta se andocheaz, apoi la un nou click, revine la


starea iniial. La intrarea cu mouse-ul deasupra butonului cu eticheta Rou,
acesta i schimb culoarea i eticheta, iar la ieirea mouse-ului revine la
starea iniial. Utilizai metoda Application.Exit() de cte ori dorii s
ncheiai aplicaia.
148 Partea a II-a. Program are W indow s cu V isual C# E xpress Edition

C ontroalele L a b e i i L inkLabel

Controalele Labei au menirea de a plasa un text pe o form, cu informaii


pentru utilizator. Aa cum putei vedea din fereastra P roperties, controalele Labei
suport evenimente, ns de regul nu le vei trata.
.NET Framework definete i clasa LinkLabel, derivat din Labei.
Aceasta afieaz o poriune din text ca un hyperlink. La un click pe hyperlink, putei
deschide pagini WEB, lansa n execuie diverse diverse aplicaii i n general putei
utiliza handler-ul de tratare a evenimentului C lick, pentru orice aciune.

Aplicaia LabelExample

Vom realiza un proiect care exemplific cel mai simplu mod de utilizare a
etichetelor.

1. n meniul File, alegei NewProject.

2. In panoul Tem plates, selectai W in d o w s Form s A p p lic a tio n .

3. In cmpul Name, scriei de exemplu L abelE xam ple pentru numele


proiectului.

4. Din T o o lb o x, tragei cu mouse-ul pe suprafaa formei un control de tip


Labei, i dou controale de tip LinkLabel.

5. Selectai controlul de tip Labei i n fereastra P ro p e rtie s setai valoarea


proprietii T ext la valoarea "Un control de tip Labei".

6. Selectai primul control LinkLabel i n fereastra P ro p e rtie s setai


proprietatea Text la valoarea "V izitati www.yahoo.com" , apoi expandai
nodul LinkArea i setai proprietatea S ta rt la valoarea 9. Aceasta
nseamn c link-ul ncepe dup al 9-lea caracter al valorii proprietii
Text.

| AutoEllipsis False Lj|


ContextMenuStrip (none) -rr*;
Enabled True
B 9; 24 Q
Start 9
Length 24
LinkBehavior SystemDefault

7. Selectai primul control de tip LinkLabel, iar n fereastra P roperties,


apsai butonul Events. Facei dublu click pe evenimentul L in kC licke d .
Scriei n corpul handler-ului codul:

private void linkLabell_LinkClicked(object sender,


LinkLabelLinkClickedEventArgs e)
C apitolul 7. Controalele W indows F orm s 149

// Schimb culoarea link-ului dup click


linkLabell.LinkVisited = true ;

// Schimb textul n controlul Labei


labell.Text = "Se viziteaz www.yahoo.com";

// Folosete metoda Process.S t a r t () pentru a


// deschide un URL cu browserul implicit
System.Diagnostics.Process.S t a r t (
"h t t p :// w w w .y a h o o .c o m ")
}

8. Selectai al doilea control LinkLabel. n fereastra P ro p e rtie s setai


proprietatea T ext la valoarea " Lansai Notepad", apoi expandai nodul
LinkArea i setai proprietatea S tart la valoarea 8. Aceasta nseamn c
link-u\ ncepe dup al 8-lea caracter al valorii proprietii Text:

9. Selectai controlul L inkLabel cu textul Lansai Notepacf, iar n fereastra


P ro p e rtie s apsai butonul Events. Facei dublu click pe evenimentul
L in kC licke d . Scriei n corpul handier-ului codul:

private void linkLabel2_LinkClicked(object sender,


LinkLabelLinkClickedEventArgs e)
{
linkLabel2.LinkVisited = true;
labell.Text = "S-a lansat Notepad";

// Folosete metoda S t a r t () pentru a lansa Notepad


System.Diagnostics.Process.S t a r t ("notepad");

10. Lansai n execuie cu F5.


150 Partea a Il-a . P rogram are W indow s cu V isual C# E xpress Edition

LaraatiNoteoad

Observaii:
Proprietatea Link A r e a a unui control L inkLabel, este o structur care
reine poziia primului caracter al link-ului i numrul de caractere din link.
lat cum putei crea programatic un L in kL ab e l care va fi adugat pe o
form:

v o i d A d d L i n k L a b e l ()
{
// Creaz o etichet
LinkLabel lnk = new LinkLabel ();

lnk.Text = "Vizitati w w w . y a h o o . c o m ";

/ / 9 -poziia primului caracter al link-ului


l n k .LinkArea = new LinkArea(9, 24);

// Poziia de amplasare pe form


lnk.Lo c a t i o n = new Point(20, 20);

// Adaug controlul pe forma curent


this.Controls.Addlnk) ;
}

Aceast metod se poate apela n constructorul clasei formei, sau


ntr-un handler de eveniment.
> Metoda Process .Start () din spaiul de nume Sys t e m . D i a g n o s t i c
este suprancrcat i este util oricnd dorii s lansai n execuie o alt
aplicaie din propria aplicaie. De exemplu, apelul urmtor deschide
fiierul Salut.doc cu WordPad:

S y s t e m . D i a g n o s t i c a . P r o c e s s .S t a r t ( " w o r d p a d . e x e " ,
@"c:\Salut.doc");
C apitolul 7. Controalele W indows F orm s 151

C ontroalele R adioB utton, C heckB ox i G rou pB ox

Aa cum am mai artat, controalele Button, RadioButton i CheckBox


deriv direct din clasa ButtonBase.
Un buton radio poate fi apsat sau nu. Se folosete atunci cnd utilizatorul
trebuie s fac o singur alegere ntre mai multe opiuni, iar acele opiuni se exclud
reciproc. De exemplu, trebuie s marcheze dac e brbat sau femeie, dac e
cstorit sau nu, etc.
Butoanele radio nu se pun niciodat direct pe form. Ele se grupeaz ntr-un
control container, de regul un GroupBox. n interiorul unui control container, radio
butoanele devin coerente din punct de vedere logic, n sensul c un singur buton
poate fi selectat la un moment dat.
Butoanele de validare (checkbox-ur\\e) permit utilizatorului s aleag una
sau mai multe opiuni. De exemplu, utilizatorul poate sa bifeze mai multe sporturi
preferate. Pot s fie sau nu incluse n controale container.
Controalele RadioButton i CheckBox au proprietatea numit Checked,
care indic dac controlul este selectat sau nu.

Aplicaia GroupRadioCheck
Proiectul ilustreaz un mod simplu de utilizare a controalelor RadioButton,
CheckBox i GroupBox.

1. Din meniul File, alegei NewProject.

2. n panoul Templates, selectai Windows Forms Application.

3. In cmpul Name, scriei de exemplu G roupR adioC heck pentru numele


proiectului.

4. Selectai forma. n fereastra P roperties setai proprietatea Text la


valoarea Formular.

5. Din Toolbox, tragei cu mouse-ul pe suprafaa formei un control de tip


GroupBox. n fereastra P roperties, etichetai controlul, setnd
proprietatea Text la valoarea Excursii.

6. Din Toolbox, tragei cu mouse-ul pe suprafaa primului GroupBox, nc


dou controale de tip GroupBox. n fereastra Properties, selectai-le pe
rnd i etichetai-le astfel: Tara, respectiv Transport.
152 Partea a II-a. P rogram are W indow s cu V isual C# E xpress Edition

Excursii

Tara Transport

7. Pe suprafaa groupbox-ului cu numele Tara, aducei din T o o lb o x cinci


radio butoane. Selectai-le pe rnd i din fereastra P roperties setai-le
proprietile Text (etichetele) la valorile: Austria, Grecia, Frana, Italia,
Germania.

8. Pe suprafaa groupbox-ului cu numele Transport, aducei din T o o lb o x


dou butoane de validare. Selectai-le pe rnd i din fereastra P roperties
setai-le proprietile T ext (etichetele) la valorile: Avionul, respectiv
Balonul.

9. Pe suprafaa groupbox-ului cu eticheta Excursii, aducei dou butoane.


Selectai primul buton i setai proprieatea T ext la valoarea <SVerifica.
Ampersandul are ca efect sublinierea caracterului care i urmeaz,
informnd userul c poate s acceseze butonul de la tastatur cu
combinaia: A lt + litera subliniat. Selectai cel de-al doilea buton i setai-i
proprietatea T ext la valoarea &lesire.

!S l

Excursii

T ara Transport
O Austria P I Avionul

0 Grecia O Balonul

O Frana

O Italia | Verifica )

O Germania [ Ieire |

TP'"'" 1 1 u

10. Facei dublu click pe butonul Verifica, pentru a trata evenimentul C lick. n
handler-ut de eveniment, scriei codul evideniat cu bo ld :

private void buttonl_Click(object sender,


EvantArgs e)
C apitolul 7. C ontroalele W indows F orm s 153

{
string msg = "Vom pleca in
// Verific care dintre butoanele radio e apsat
if (radioButtonl.Checked)
msg += radioButtonl.Text;
if (radioButton2.Checked)
msg += radioButton2.T e x t ;
i f {radioButton3.Checked)
m s g += radioButton3.Text;
if (radioButton4.Checked)
msg += radioButton4.Text;
if (radioButton5.Checked)
msg += radioButton5.T e x t ;

// Verific starea butoanelor de validare


bool firstDest = false;
if (checkBoxl.Checked)
{
msg += " cu " + checkBoxl.Text;
firstDest = true;
}
if (checkBox2.Checked)
if (firstDest)
msg += " si cu " + checkBox2.Text;
else
msg += " cu " + checkBox2.T e x t ;

// Afieaz mesajul
MessageBox.Show(msg + " !");

// Restablete starea iniial


checkBoxl.Checked = false;
checkBox2.Checked = false;
radioButtonl.Checked = true;
}

11. Facei dubiu click pe butonul Ieire, pentru tratarea evenimentului C lic k . In
Editorul de Cod vei scrie:

private void button2_Click(object sender, EventArgs e)


{
Application.E x i t (); // Ieire din aplicaie
}

12. Rulai aplicaia cu F5 sau acionai butonul ^ din Standard Toolbar.

La rulare, obinei:
154 Partea a II-a. P rogram are W indow s cu V isual C# Express Edition

MessageBox
Excursii
Tara T ransport

O Austria 0 Avionul

O Grecia 0 Balonul Vom p leca in G erm ania cu A vio n u l si cu B a lo n u l!

O fra n a

O 'talia [ Verifica ]

( - ) Germania [ Ieire )

C ontrolul T extB o x

Platforma .NET ofer dou controale pentru editare de text: TextBox i


RichTextBox. Ambele clase deriv din clasa TextBoxBase. TextBox este un
control cu mai puine faciliti dect RichTextBox, ns este foarte util pentru
introducerea de date mici ca dimensiuni de la tastatur.

Principalii membri ai clasei TextBox

De la clasa printe TextBoxBase, motenete proprieti i metode pentru


manipularea textului, cum este selectarea textului, copiere, tiere i lipire din
clipboard, ca i un mare numr de evenimente. Descriem o parte dintre membrii
clasei.

P ro p rie t i:

Multiline Returneaz sau seteaz o valoare boolean care indic


dac text box-ul poate avea mai multe linii
AcceptsReturn - Returneaz sau seteaz o valoare care indic dac la
apsarea E nter ntr-un T e xtB o x multilinie se va trece la
linie nou sau se activeaz butonul implict al formei
PassworChar Returneaz sau seteaz un caracter folosit s mascheze
parola
Text Returneaz sau modific textul n control

Metode:

C o p y () Copiaz textul selectat n Clipboard


Paste() Lipete n control coninutul Clipboard-ului
C apitolul 7. C ontroalele W indows F orm s 155

Cut () - Mut textul selectat n Clipboard


C l e a r () - terge textul din control
S elect() - Selecteaz un interval de text n control
SetBounds - Seteaz limitele controlului, la locaia i la dimeniunile
specificate
U n d o () - Anuleaz ultima operaie efectuat n text box

Evenim ente:

C lic k - Se declaneaz la click n control


G o tF o c u s - Se declaneaz cnd controlul primete focusul
Leave - Se declaneaz cnd focusul prsete controlul
T e x tC h a n g e d - Se declaneaz cnd proprietatea T e x t se schimb.

Aplicaia TextBoxExample

Proiectul urmtor relev cteva dintre caracteristicile controlului TextBox.

1. Creai un proiect de tip W indow s Form s A p p lic a tio n , cu numele


TextBoxExample.

2. Din T oolbox, plasai cu mouse-ul pe suprafaa formei trei controale de tip


Labei, trei controale de tip T extB ox i un buton, apoi aranjai-le aa ca n
figur:

i i i m k f y ! 7 ! | | |

ID-ul:
-- --------- ------~ - :
Parola:
----------------- ----- --

CNP:

I Autentificare |

3. Selectai primul control de tip TextB ox. Din fereastra P roperties setai
proprietatea Name la valoarea idTextBox. Setai n acelai mod pentru al
doilea control proprietatea Name la valoarea p a r o l a T e x t B o x i
c npTextBox pentru al treilea control de tip TextBox. Pentru eticheta
CNP, setai proprietatea Name ia valoarea cnpLabel, iar pentru buton,
autentifButton.
156 Partea a Il-a . Program are W indow s cu V isual C# E xpress Edition

4. Iniial, numai primul cmp text este activ, celelalte dou fiind dezactivate,
n acest scop se utilizeaz proprietatea Enabled. Dorim ca nc de la
apariia formei controalele parolaTextBox i cnpTextBox s fie
dezactivate. Pentru aceasta, vom scrie codul necesar n constructorul
formei. Selectai forma, apoi n P roperties setai cmpul Name la valoarea
TextBoxEx. n felul acesta, ai modificat numele clasei formei, care iniial
era F o rm l. Facei click drept n SolutionExplorer pe numele formei i
alegei View Code. n constructorul clasei introducei urmtoarele:

public Tex t B o x E x O // Constructorul formei


{
InitializeComponent();
// Caracterul '*' mascheaz parola
parolaTextBox.PasswordChar =

// Controlul de tip TextBox pentru parol


// este iniial vizibil, dar dezactivat
parolaTextBox.Enabled = false;

// Eticheta i TextBox-ul pentru CNP, ca i


// butonul Autentificare sunt iniial invizibile
cnpLabel.Visible = false;
cnpTextBox.Visible = false;
autentifButton.Visible = falsa;
}

5. Pentru testarea validitii ID-ului introdus, tratai evenimentul


P review K eyD ow n:

private void idTextBox_PreviewKeyDown(object sender,


PreviewKeyDownEventArgs e)

// Dac tasta apsat este Tab


if (e.KeyCode == Keys.Tab)
if (idTextBox.Text == "ionel")
// ID corect, activm cmpul pentru parol
parolaTextBox.Enabled = true;
else
MessageBox.Show("Utilizatorul nu exista!");
}

6. Tratai evenimentul Preview K eyD ow n pentru verificarea parolei:

private void parolaTextBox_PreviewKeyDown


(object sender, PreviewKeyDownEventArgs e)
{
// Dac tasta apsat este Enter
if (e.KeyCode == Keys.Enter)
C apitolul 7. C ontroalele W indows F orm s 157

{
// Dac cmpul Text are valoarea "parola"
if (parolaTextBox.Text "parola")
<
// Eticheta i controlul de tip text
// pentru CNP devin vizibile
cnpLabel.Visible = true;
cnpTextBox.Visible = true;

// TextBox-ul pentru CNP primete focusul


cnpTextBox.F o c u s ();

// Butonul devine vizibil pe form


autentifButton.Visible = true;
>
else
{
MessageBox.Show("Parola incorecta!);
// terge textul din control
parolaTextBox.C l e a r ();
}
}
}

7. Pentru CNP, dorim s nu permitem introducerea altor caractere dect cifre.


Pentru aceasta, tratai evenimentul KeyPress i pentru toate caracterele
cu codul ASCII mai mic dect 48 sau mai mare dect 57, setai
proprietatea Handled la valoarea true. n felul acesta, evenimentul nu
mai este transmis controlului, iar caracterul apsat nu va mai fi afiat.

private void cnpTextBox_KeyPress(object sender,


KeyPressEventArgs e)
{ // Daca nu e cifr, nu se afieaz
if (e.KeyChar < 48 || e.KeyChar > 57)
e.Handled = true;
)

8. Tratai evenimentul C lic k pentru butonul Autentificare. Dublu click pe buton


n Form Designer. Vei cere ca numrul total de cifre s fie 13:

private void autentifButton_Click(object sender,


EventArgs e)
(
// Dac lungimea CNP este incorect
if (cnpTextBox.Text.Length != 13)
{
MessageBox.Show("CNP incorect!");
// Se terge textul din control
cnpTextBox.Clear () ,-
158 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress E dition

else
MessageBox.S h o w {"Autentificare cu succes!");
}

9. Compilai i rulai cu F5.

Utilizatorul va completa primul cmp de text cu ID-ul lonet', dup care va apsa
Tafa, al doilea cmp cu parola parola", dup care apas E nter, iar in al treilea va
trece un numr format din 13 cifre, apoi va face click pe buton. Aplicaia verific
corectitudinea ID-ului, a parolei i a CNP-ului, ntr-un mod, desigur rudimentar, dar
suficient pentru ceea ce ne-am propus.
La rulare, nainte de introducerea parolei, avem:

1 TextBoxControl 3 (M )

ID-ul: | ionel

Parola:

Dup introducerea parolei parola i a unui ID format din 13 cifre:

ffT ex o xC o n tw t' (Tjnjcl


ID-ul: ionel

Parola:

CNP: 1900125060780 j

Autentificare cu succes!

[ Autentificare j OK

Vei constat c acele caractere tastate care nu sunt cifre nu apar n


TextBox-u\ pentru CA/P.

De reinut:
* Proprietatea P assw ordC har stabilete caracterul care mascheaz textul
introdus de utilizator.
C apitolul 7. C ontroalele W indows Form s 159

Proprietatile Enabled i V isib le au valorile truc sau false. Implicit


este true. Valoarea false pentru Enabled, aduce controlul n stare
inactiv, n timp ce false pentru V isib le face controlul invizibil pe
form. Sunt caracteristici ale tuturor controalelor, ntruct se
motenenesc de la clasa de baz Control.
Evenimentele P review K eyD ow n sau K eyPress au fost alese i n
funcie de abilitile parametrilor handler-elor lor. De exemplu, obiectul
KeyPressEventArgs, parametru al metodei cnpTextBox_KeyPress
conine proprietatea KeyChar, necesar identificrii codului ASCII al
caracterului introdus.
Metoda Focus ( ) , motenit de la clasa Control, seteaz focusul pe
controlul curent.

E f e m e n t e d e S t i t
Este recomandabil ca n aplicaiile n care folosii m ai multe controale, s
introducei propriile nume pentru referine i tipuri. Numele trebuie s fie sugestive,
adic s indice menirea i tipul controlului. Exemplu: id T e x tB o x ,
p a r o la T e x tB o x , etc. Numele claselor trebuie s nceap cu liter mare, de
exemplu T extB oxE xam ple. n felul acesta vei distinge uor referinele i tipurile.

Focusul Controalelor

Controlul care primete intrrile de la tastatur este cel care are focusuE .
n oricare moment, un singur control al aplicaiei poate avea focusul. Schimbarea
focusului se face acionnd tastele sgei, tasta Tab, sau mouse-ul.
Ordinea n care controalele primesc focusul se stabilete programatic cu
ajutorul proprietii Tablndex. Controlul cu valoarea 0 pentru T ablndex primete
primul focusul. Visual C# 2008 permite stabilirea design time a focusului
controlalor. n meniul View, alegei Tab Order, apoi facei click pe etichete pentru
modificri.

ji j < \ | Formt'


I I Are "focus" j Nu are focus Are "focus Nu are "focus"

I I
u
I I Nu are "focus" j Nu are "focus" Nu are "focus" Nu are "focus"

......................... - .............J
Figura 7.1 Focus stabilit design time Figura 7.2 Focusul la rulare
160 Partea a Il-a . Program are W indow s cu V isual C # E xpress Edition

Chei de accesare a controalelor


n timpul rulrii, un control poate primi n mod direct focusul de la tastatur,
srind peste ordinea stabilit prin T ablndex, cu ajutorul unei combinaii de taste:
A lt + Caracter. Este nevoie pentru aceasta ca valoarea proprietatii T e xt s
conin caracterul ampersand. Pentru exemplul de mai jos, proprietatatea T ext are
valorile: SButonl, B&uton2, SEticheta.
Label-urile au Tablndex, chiar dac ele nu pot primi focusul. Dac le
accesai cu o combinaie de chei, controlul care urmeaz etichetei n ordinea de
indexare, va primi focusul.
Dup combinaia Alt+E, C om boB ox-ul va primi focusul:

Controalele invizibile sau cele dezactivate nu pot fi accesate cu tasta Tab, i nu pot
primi focusul, chiar dac li s-a asociat un index de tabulare design time sau run
time.

Probleme propuse

1. Realizai o aplicaie care folosete un text box ca editor de text. Explorai


proprietile clasei T e xtB o x i testai-le pentru acest control (Exemplu:
culoarea fontului, dimensiune, culoare backgound, etc).
2. Realizai o aplicaie care utilizeaz un T e x tB o x pentru introducerea
textului. La fiecare caracter introdus, culoarea fundalului i a textului
trebuie s se schimbe (alegei cte o list de culori complementare pentru
text i fundal, care se vor repeta ciclic).
3. Realizai un mic proiect a crui fereastr reprezint un formular care
trebuie completat de cte un elev, atunci cnd se nscrie la facultate.
Pentru preluarea datelor, se vor utiliza controale de tip TextB ox,
C h e ckB o x i R a d io B u tto n . La apsarea unui buton, toate datele
intruduse se vor lista ntr-un control de tip T extB ox, ntr-o formatare aleas
de dumneavoastr.
4. Creai o aplicaie care preia adresa si numrul de telefon ale unei
persoane (introduse n controale de tip text diferite) i afieaz ntr-un
MessageBox toate informaiile culese.
5. Implementai o aplicaie care preia o comand de produse efectuat de
ctre un client i afieaz toate elemente sale
C apitolul 7. C ontroalele W indow s F orm s 161

C o ntroalele M enuS trlp i C ontextM en uS trip

Meniurile sunt controale familiare n peisajul aplicaiilor de zi cu zi. De


exemplu, utilitarul clasic N otepad are un meniu din care utilizatorul poate seta
diverse aciuni de formatare a textului sau de editare. Cu ajutorul controlului de tip
container M enuS trip se pot crea deosebit de uor asemenea meniuri.
Meniurile de context definite cu C on te xtM e n u S trip se acceseaz cu click
drept i sunt folosite deseori n editare de text sau oriunde dorii s avei acces
rapid la anumite opiuni, cum ar fi Cut, Copy, Paste. Un meniu contextual se
asigneaz ntotdeauna unui control, acelui control pe care facei click drept.

Principalii membri ai clasei MenuStrip


Clasa este bogat n proprieti, metode i evenimente. Din fericire, nu avei
nevoie dect extrem de rar s modificai valorile implicite ale proprietilor. De
asemenea, din mulimea de evenimente, tratai de regul doar evenimentul Click.
Urmeaz o prezentare selectiv a membrilor:

P ro p rie t i:

Anchor - Determin modul n care se redimensioneaz controlul


n raport cu containerul su.
Backgrounglmage - Returneaz sau seteaz imaginea afiat n control
ClientSize - Returneaz sau seteaz nlimea i limea zonei
client a controlului.
ContextMenu - Seteaz meniul de context asociat
Text - Reprezint textul asociat controlului

Metode:

F i n d F o r m () - Returneaz o referin la forma pe care se gsete


controlul
H id e () - Ascunde controlul
Show() - Afieaz controlul

Evenim ente:

Click - Se declaneaz la click n control


; i
MenuActivate - Se declaneaz cnd ut lizatorul acceseaz meniul cu
>: tastatura sau mouse-ul
$ & Leave
f I - Se declaneaz cnd focusul prsete controlul
TextChanged - Se declaneaz cnd proprietatea Text se schimb.
- I
? &
I3
V
) .
162 P artea a Il-a . Program are W indow s cu V isual C# E xpress Edition

Aplicaia MenuExam ple

Proiectul pe care l vom realiza pentru acomodarea cu cele dou controale


implementeaz:
Un editor de text rudimentar cu ajutorul unui control TextB ox.
Operaiile cut/copy/paste . Aceste sunt accesibile att dintr-un meniu ct
i dintr-un meniu contextual.

Urmai paii:

1. Creai un nou proiect de tip Windows Forms Application, cu numele


MenuExample.

2. Din T o o lb o x tragei cu ajutorul mouse-ului un control M enuS trip pe


suprafaa formei.

3. Facei click pe caseta controlului, acolo unde scrie Type Here, i creai un
prim meniu numit Fiier, cu opiunile Nou i Ieire:

.Form1.

Tyjc I' ?

4. Creai un al doilea meniu cu numele E ditare i opiunile Copiaza,


Decupeaz i Lipete: 1
C apitolul 7. C ontroalele W indows F orm s 163

5. Din T o o lb o x alegei un contrlol TextB ox i plasai-l pe suprafaa formei.

6. Setai pentru T e xtB o x proprietatea M u ltilin e la true. Acest lucru se poate


face din P roperties sau mai simplu cu ajutorul meniului contextual care
apare prin click pe sgeata din colul dreapta sus a controlului:

Multiline

7. Din T o o lb o x tragei pe suprafaa ferestrei aplicaiei un control de tip


C ontextM enuS trip. Selectai controlul i introducei opiunile: Copiaza,
Decupeaz, Lipete:

ilt'Rfer'':'\; Editare 1

ContextMenubtrip
fj Copiaza
.Ji Decupeaz
3 SiLipestel
*- i: ;

8. Acum vei asigna meniul de context controlului T extB ox. Selectai controlul
T extB ox i n P roperties atribuii proprietii C o n te xtM e n u S trip valoarea
contextMenuStripl, adic referina la obiectul de tip meniu contextual
al aplicaiei:
164 Partea a Il-a . P rogram are W indow s cu V isual C# E xpress Edition

: CharacterCasing Normal
|B | c o n tex tM e n u S tri v
!; S (AppIicationSetting:
; | E (DataBindings)

9. n continuare, vei trata evenimentul C lick pentru fiecare dintre opiunile


meniului i ale meniului contextual:
a. n meniul Fiier, dublu click pe opiunea Nou. n corpul metodei
handler, scriei: textBoxl .Clear () ;. n felul acesta, tergei
textul din controlul TextB ox.
b. n meniul Fiier, dublu click pe opiunea Ieire. n corpul metodei
handler, scriei: Application.Exit) Astfel se iese din
aplicaie.
c. n meniul Editare, dublu click pe opiunea Copiaza. n corpul
metodei handler, scriei: textBoxl.Copy ();. Metoda copiaz n
clipboard textul selectat.
d. n meniul Editare, dublu click pe opiunea Decupeaz. n corpul
metodei handler, scriei: textBoxl. Cut <);. Metoda terge din
control textul selectat i i copiaz n clipboard.
e. n meniul Editare, dublu click pe opiunea Lipete. n corpul
metodei handler, scriei: textBoxl. Pas te ( ) ; . Metoda scrie n
control textul memorat n clipboard.
f. Selectai meniul contextual din bara gri, din partea de jos a Form
Designer-ului. Vei face dublu click pe fiecare opiune a meniului
contextual i vei trata evenimentul C lick n aceeai manier n
care ai procedat cu opiunile Copiaz, Decupeaz i L ip e te ale
meniului aplicaiei.

10. Compilai i rulai cu F5.

n orau-n care plou de trei ori pe sptmn


Un btrn i o btrn

Copiaza

^ Decupeaz
| Lipete
C apitolul 7. C ontroalele W indows F orm s 165

Forme
O form este un tip special de control care reprezint o fereastr. Este
folosit ca suport pentru alte controale. Prin setarea proprietilor se obin diferite
tipuri de ferestre, avnd diverse dimensiuni, aparene, stiluri i culori. Formele sunt
instane ale clasei Form.

Principalii membri ai clasei Form

Din galeria de membrii ai acestei clase, prezentm:

P ro p rie t i:

ClientSize - Returneaz i seteaz suprafaa util a formei, pe care se


pot plasa controale sau se poate desena.
DialogResult - Seteaz valoarea pe care o returneaz o form cnd
funcioneaz ca dialog modal.
Modal - Stabilete dac o form se afieaz sau nu ca dialog
modal.
Size - Returneaz sau modific dimensiunie formei.

Metode:

A c t i v a t e () - Activeaz forma i i transfer focusul


Close () - nchide forma

Invalidate() - Invalideaz ntreaga suprafa a formei, fapt care


cauzeaz redesenarea ei
Show() - Afieaz forma
S h o w D ia lo g O - Afieaz forma ca dialoq modal
Text - Specific un text n bara de titlu

Evenim ente:

Closing - Se declaneaz cnd forma se nchide


Load - Se declaneaz nainte ca forma s fie afiat pentru
prima oar.
166 Partea a II-a. P rogram are W indow s cu V isual C# Express E dition

Crearea form elor


1. C re a re a p r o g r a m a tic a fo r m e lo r
n mod programatic, o form se creaz foarte simplu:

Form f = new F orm(); // Se instaniaz forma


f .S h o w (); // Se afieaz

O metod obinuit de creare a unei forme este de a defini o clas derivat din
clasa Form:

class FormaMea Form


{
public FormaMea () // Constructorul clasei
{
}
// Ali membri ai clasei (cmpuri, proprieti, metode)
}

Dintr-o alt metod a aplicaei, instaniai forma:

FormaMea f = new FormaMea();


f .S h o w ();

2. Crearea form elor cu ajutorul Form Designer -ului

La crearea unui nou proiect de tip Windows Forms, mediul integrat genereaz
o clas cu numele implicit Forral, iar aceast clas se instaniaz Tn Main ():

Application.Run(new F o r m l ());

Putei aduga proiectului oricte alte forme, n felul urmtor:


n S o lu tio n E x p lo re r, acionai click drept pe numele proiectului, alegei Add, apoi
Windows F o rm ...:

3 Solution FormExample (1 project)


; - .L E S E E S ?

I - 4dj Proper ; > l : Build


' S- Refers Rebuild
I a j f l ] Forml
! 33- sj Form2 Publish...

:T1 New Item... : A dd;

j i i i ] ' Existing Item .., Add Reference...

r*~, New Folder Add Service Reference.,

-: Windows Form. Set as Startup Project

51 User Control... Debug

Ca variant alternativ, click drept pe numele proiectului, alegei Add, apoi New
Item....
C apitolul 7. C ontroalele W indows Form s 167

n fereastra Add New Item - [nume proiecf\ selectai iconul Windows Form i
introducei un nume pentru noua form:

Dialoguri modale i dialoguri nemodale

Una dintre forme este fereastra de baz a aplicaiei. Celelalte forme


reprezint ferestre care pot fi fcute s apar la un moment dat.

Dialoguri modale
Anumite tipuri de ferestre se prezint ca dialoguri cu utilizatorul. Acesta
introduce date n controale, pe care apoi le valideaz sau nu (apsnd de exemplu
butoanele OK sau C ancel). Acest tip de fereastr dialog nu permite utilizatorului s
acceseze alte ferestre ale aplicaiei pn cnd dialogul nu este nchis. De
exemplu, n M icrosoft Word, cnd alegei Open n meniul File, se deschide un
dialog care v cere s alegei un fiier. Fereastra blocheaz aplicaia i nu putei
ntreprinde nici o alt aciune n editor, pn n momentul n care ai nchis dialogul.
Un asemenea tip de dialog, se numete d ia lo g m odal.
Un dialog modal este o form care se deschide cu metoda showDialog ():

class Forma : Form


{
// membrii clasei
1

Forma f = new Forma () ;


f .ShowDialog();
168 Partea a Il-a . Program are W indow s cu V isual C# E xpress E dition

Aplicaia DialogModal
Realizm un proiect de tip consol care lanseaz o form ca dialog modal.
Urmai paii:

1. n meniul File, alegei New Project.

2. n panoul dialogului New Project selectai Empty Project, iar n caseta text
Name, introducei numele proiectului: DialogModal.

3. n Solution Explorer, executai click drept pe numele proiectului i alegei


Add, apoi New Item....

4. n dialogul A dd New Item, selectai iconul Code File, apoi n caseta Name,
introducei numele fiierului: Modal.cs.

5. Fiierul Modal.cs se deschide n Editorul de Cod. Introducei codul:

using System;
using System.Windows.F o rms;

class Forma : Form


{
}

class Pogram
1
public static void Main)
{
Forma f = new Forma); // Instaniere

// Text n bara de titlu


f.Text = "Dialog Modal";

// Dialogul modal devine vizibil


f .ShowDialog();

A p p l i c a t i o n - R u n (); // Lanseaz aplicaia


}
}

6. nc nu putem compila, pentru c proiectul de tip consol nu introduce n


mod automat referine la bibliotecile dinamice .NET care implementeaz
spaiile de nume S ystem .W indow s i S yste m .W in d o w s.F o rm s. Vom
aduce aceste referine astfel: n S o lu tio n E xplorer, click drept pe folderul
References:
C apitolul 7. C ontroalele W indows F orm s 169

Solution Explorer - Solution 'DialogModl* (1 ... - X ;.0|


;1
M 3s J j .
Solution 'DialogModall' (1 project)
S *] DialogM odall
--
c ) Modal.cs j \ Add Reference...

Add Service R eference...


I

7. n dialogul dcfc/ Reference, selectai pe tab-ul .NET intrarea System , apoi


repetai pasul 6 i adugai o referin la bibliotecile
S ystem .W indow s.F orm s:

A dd R e fe re n c e .. 4- *
.NET ; C O M _ R e j e c t s . Brow se Recent

: C om ponent Name * Version Runtime IC


System .Transactions 2^0.0.0 v 2 .0.5 0 7 2 7
j System .W e b 2.0 .0 .0 v 2 .0.5 0 7 2 7
System . W eb. Extensions 3.5 .0 .0 v 2 .0.5 0 7 2 7
System . W eb. Extensions.Design 3 .S .0 .0 v 2 . 0.5 0 7 2 7
; System .W eb,M obile 2.0 .0 .0 v 2 .0 .5 0 7 2 7
i System .W eb.RegularExpressions 2.0 .0 .0 v 2 .0 .5 0 7 2 7
! System .W eb.Services 2.0 .0 .0 v 2 .0.5 0 7 2 7 c
S y s t e m . W ind ow s.Form s t 2.0 ,0 .0 V2.0.50727 E
! System .W indow s.Presentation 3 .S .0 .0 v2 .0 .50 72 7
; System.W orkflow.Activities 3.0 .0 .0 v 2 .0.5 0 7 2 7
; System .W orkflow .Com ponentM odel 3.0 .0 .0 v2 .0 .50 7 2 7
System .W orkflow .Runtim e 3..0. v 2 .0.5 0 7 2 7 -
; System .W orkflow Services 3.5 .0 .0 v2 .0.5 0 7 2 7
; System.Xml 2.0 .0 .0 v 2 .0.5 072 7
! ^v<tftm.Xml.! inn ... v 2 .n .5 n 7 ?7 ry
< :
v

OK Cancel

8. Compilai i rulai aplicaia cu F5. La rulare obinei:


tf

170 P artea a I l-a . P rogram are W indow s cu V isual C# E xpress Edition

Dialoguri nemodale

Dialogurile nemodale sunt ferestre care nu ntrerup execuia aplicaiei. Un


dialog nemodal nu mpiedic utilizatorul s execute aciuni n alte ferestre ale
aplicaiei. Se utilizeaz n special ca bare de instrumente. Gndii-v la toolbox-
urile din Paint sau Word, sau chiar T o o lb o x din Visual C# Express 2008.
Afiarea se face cu metoda show (); La nchiderea unei forme cu ciose (),
toi membrii clasei (de exemplu controalele de pe form) se distrug.
Ca exerciiu de creare programatic a unui dialog nemodal, reluai toi paii
aplicaiei DialogModal (redenumii ca DialogNemodal) i facei o singur modificare
n cod: nlocuii f .ShowDialog () cu f .Show ();

Aplicaia M odalDialogExam ple

D escrierea a p lic a ie i:

> Construiete un dialog modal care se deschide la apsarea unui buton al


formei printe a aplicaiei.
> Datele pe care utilizatorul le introduce ntr-un control al dialogului modal 4
se transfer unui control al clasei printe.
> Anticipeaz modul de utilizare a unui control L istB o x.

Urmai paii:

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


tf ModaiDialogexample.
$
2. Din T o o lb o x plasai pe form cu ajutorul mouse-ului un control de tip |
L is tB o x i dou butoane. Setai proprietatea T ext pentru celor dou
& butoane astfel:


l

ilistBoxl f Adauga ]
i
i

1
i i
l
i | Ieire |

3. Adugai o nou form proiectului. n S o lu tio n E xplorer, click dreapta p e !


numele proiectului, alegei Add, apoi Windows Form ... i validai cu OK.

1
C apitolul 7. C ontroalele W indows F orm s 171

4. n S o lu tio n E xplorer, dublu click pe numele Form2 (n cazul n care nu ai


redenumit noua form).

5. Aducei din T o o lb o x un control T e xtB o x i un buton, ca n figur:

=,s
OK

6. n S o lu tio n E xplorer, acionai click drept pe numele Form2, apoi alegei


View Code. n clasa Form2 definii membrii:

// Cmp care reine textul introdus n textBoxl


private string item;

// Proprietate care returneaz valoarea textului


public string Item
{
get { return item; }
)

7. Tratm evenimentul C lick generat la apsarea butonului OK. Acionai


dublu click pe buton. Completai codul evideniat n B old:

private void buttonl Click(object sender, EventArgs e)


{
// Salvm textul introdus n control,
item = textBoxl.T e x t .T r i m ();

// nchidem forma F o r m 2 .
C l o s e ();

8. Dorim ca Form2 s se nchid i la apsarea tastei Enter. Tratm


evenimentul K eyD ow n pentru controlul T extB ox. Selectai controlul. n
fereastra P rop erties apsai butonul E ve n ts (fulgerul) i facei dublu click
pe evenimentul KeyDown. Introducei codul:

private void textBoxl_KeyDown(object sender,


KeyEventArgs e)
{
// Dac tasta apsat are codul tastei Enter
if (e.KeyCode == Keys.Enter)
{
item = textBoxl.T e x t .T r i m (); // Memorm textul
Close(); // nchidem forma
1
}
172 P artea a Il-a . P rogram are W indow s cu V isual C# E xpress E dition

9. n scopul de a ni se permite s accesm proprietatea Item a clasei Form2


din metodele clasei Forml, modelm o relaie de coninere (containment).
Definim n Forml un cmp privat, o referin la Form2. n S o lu tio n
E xplorer, click drept pe F o rm l i alegei View Code. n fiierul F orm l.cs,
n clasa Forml, scriei:

private Form2 f ;

10. Tratm evenimentul C lick care se genereaz la click pe butonul Adauga,


aflat pe forma Forml. n S o lu tio n E xplorer, facei dublu click Form2, apoi
n Form Designer acionai dublu click pe butonul Adauga. n corpul
handler-ului introducei codul:

private void buttonl_Click(object sender, EventArgs e)


!
f = new Form2(); // Crem forma

f .ShowDialog(); // Afim dialogul modal


if ( f.Item != "") // Dac exist text
{
// Adugm itemul n listBoxl
listBoxl.Items.Add(f.Item);
}
}

11. Pentru ieire din aplicaie, facei dublu click pe butonul Ieire. n corpul
handler-ului evenimentului Click, scriei:

Application.Exit() ; // Ieire din aplicaie

12. Compilai i lansai n execuie cu F5.

La rulare, prin apsarea butonului Adauga, se deschide dialogul modal Form2.


Cnd se apas OK sau E nter, se nchide dialogul Form2, iar textul introdus
apare ca nou item n controlul L is tB o x de pe F o rm l.

I Itemul 1 Adauga
! Itemul 2
! Itemul 3

: Itemul 1) OK

Ieire
C apitolul 7. C ontroalele W indows F orm s 173

Not:

Metoda Trim() a clasei string nltur caracterele albe de la nceputul


i sfritul stringului.
Metoda Add() din apelul listBoxl. Items .Add(f. Item) ; adaug un
item ntr-un controlul referit de listBoxl.
Metoda Close () nchide forma.

IM P O R T A N T !
Cnd apelai Close {) pentru un dialog modal, fereastra nu se distruge ci
devine invizibil. Aceasta, deoarece dup nchiderea ferestrei, avei de regul
nevoie de membrii clasei, ca n aplicaia de fa:

f.ShowDialogO; // Afim dialogul modal


/ / n acest punct fereastra este nchis!
// f.Item exist i dup nchiderea dialogului, deoarece
// dialogul (obiectul de tip Form2) nu este distrus,
// ci numai ascuns,
if ( f.Item != "")
{
listBoxl.Items.Add(f.Item);
}

De reinut:

Dialogurile modale se afieaz cu metoda ShowDialogO, iar cele


nemodale cu metoda show ().
Afiarea unei forme cu Show() se poate face alternativ prin setarea
proprietii visible la valoare true. Ascunderea formei se poate face
i prin setarea proprietii Hide la false.
La nchiderea formei cu Close ( ) , dialogurile nemodale se distrug (se
distruge instana clasei).
Cnd o form este afiat ca dialog modal, apelul metodei Close () sau
un ciick pe butonul C lose (butonul cu un x n colul dreapta sus a formei)
nu distruge forma ci o ascunde, ea putnd fi fcut vizibil ulterior.
Codul care urmeaz apelului S h o wDialogO nu se execut pn cnd
forma se nchide. Dup nchiderea dialogului modal, putei utiliza n
continuare referina la clas i toi membrii clasei.

Butoane de validare a datelor

Cnd nchide un dialog modal, utilizatorul ar trebui s aib cel puin dou
opiuni: s pstreze datele pe care le-a introdus n controale sau s renune la ele.
Pentru aceasta, are nevoie de dou butoane, s le spunem O K i Cancel. Evident,
174 P artea a Il-a . Program are W indow s cu V isual C # Express E dition I

nu este suficient s etichetai cele dou butoane astfel ca s lucreze n mod


adecvat. Ca s joace rolurile dorite, se seteaz proprietatea DialogResult a
clasei Button, astfel:

Button bl = new B u t t o n ();


Button b2 = new B u t t o n ();
bl.Text = "OK"; // Poate fi i alt etichet
b2.Text = "Cancel ; // Poate fi i alt etichet

// Setm bl s returneze DialogResult.OK la click


bl.DialogResult = DialogResult.OK;

// Setm b2 s returneze DialogResult.Cancel la click


b2.Dialogresult = DialogResult.Cancel;

n felul acesta, bl va fi butonul O K al formei, ia rb 2 cel de nchidere cu Cancel.


DialogResult este o enumerare a crei membrii sunt: OK, Cancel, Abort,
Retry, None, Ignore, Yes, No.

Cum detectm n cod faptul c o form a fost nchis cu O K sau cu Cancel


? Vom analiza valoarea de retur a metodei ShowDialogO , care este tocmai una ar
dintre valorile membrilor enumerrii i anume, valoarea retumat de butonul
apsat. Secvena standard este:

DialogResult rez = f .ShowDialog();

switch (rez)
{
case DialogResult.OK :
// Ceea ce dorii s se execute dac s-a ieit cu OK
break;
case DialogResult.Cancel :
// Cod care se execut n caz c s-a acionat Cancel
break;
}

De ce vrem s tim dac forma a fost nchis cu O K sau cu C ancel ? Foarte


simplu: pentru c dac nchidei cu OK, forma este doar ascuns, i o putei utiliza
n continuare, ca i datele introduse, n vreme ce dac ai nchis cu C a n ce l, forma
se distruge m preun cu toate controalele i datele reinute n membrii clasei.

Pentru edificare, vom realiza un mic proiect de tip Windows Forms.

Aplicaia OkCancel

Aplicaia are dou butoane, cu etichetele OK i Cancel. Primului buton i se


atribuie rolul de validare a datelor, iar celuilalt de renunare. Amndou n ch id ;
forma. Se afieaz cte un message box la nchiderea formei pentru fiecare caz. '
C apitolul 7. C ontroalele W indow s F orm s 175

1. Creai un nou proiect de tip Windows Forms Application, cu numele


OkCancel.

2. Din Toolbox plasai pe form un buton. Atribuii proprietii Text valoarea


Deschide dialogul modal.

Deschide
dialogul modal

3. Adugai o form nou proiectului: n Solution Explorer, click dreapta pe


numele proiectului, alegei Add, apoi Windows Form. Clasa formei se va
numi Form2.

4. n Solution Explorer, facei dublu click pe Form2. Plasai pe suprafaa


acestei forme dou butoane, pentru care setai textele OK i Cancel.

5. Tratm evenimentul Load pentru Form2, pentru a putea seta proprietile


DialogResult pentru cele dou butoane. Desigur c putei face acest
lucru i din fereastra Properties. Executai dublu click pe suprafaa formei.
Scriei codul:

private void Form2_Load(object sender, EventArgs e)


{
// Seteaz buttonl s returneze OK la click
buttonl.DialogResult = DialogResult.OK;

// Seteaz button2 s returneze Cancel la click


b u t ton2.DialogResult = DialogResult.Cancel;
}

6. Tratm evenimentul Click pentru butonul formei Form l. Facei dublu click
pe buton. n metoda handler, introducei codul evideniat n Bold:

private void buttonl_Click(object sender, EventArgs e)


{
Form2 f = new F o r m 2 ();
DialogResult rez = .ShowDialog{);

switch (rez)
{
case DialogResult.OK;
MessageBox.Show("Dialog inchis cu OK");
break;
176 P artea a II-a. P rogram are W indow s cu V isu al C# E xpress E dition

case D i a l o g R e s u l t . Cancel:
M e s s a g e B o x .S h ow("Dialog nchis cu Cancel");
break;

La execuie, nainte de nchiderea Form2, avem:

!S Form2 j

D e schid
dialogul modal

OK

C an c e l .sfi
Htli

Dup nchiderea formei cu OK:

De reinut:

Putei desemna butoane care retumeaz valori egale cu cele ale unor
membri ai enumerrii D ialogR esult.
* Valoarea retumat la acionarea click asupra unui asemenea buton este
aceeai pe care o retumeaz metoda S h o w D i a l o g O . Acest lucru
permite ca ulterior nchiderii formei s se dirijeze fluxul de execuie al
programului n funcie de rezultatul ntors de form.

Probleme propuse

1. Testai metoda M essageB ox. Show ( t e x t , titlu, b u to a n e ) CU


toate butoanele diponibile.
C apitolul 7. C ontroalele W indows F orm s 177

2. Testai metoda MessageBox.S how () n versiunea cu 4 parametri,


folosind pe rnd toate butoanele i toate iconurile disponibile.

3. Realizai 0 aplicaie care deschide un dialog modal la acionarea unui


buton de pe forma principal. Dialogul modal conine un formular realizat
n principal cu controale text box, n care se rein date personale despre
clienii unei firme. La nchiderea dialogului modal cu O K , datele se
afieaz ntr-un format ales de dumneavoastr, ntr-un control text box
de pe forma printe. Dac dialogul modal s-a nchis cu butonul C a n c e i,
atunci nu se salveaz datele.

D ia lo g u ri p re d e fin ite

.NET ofer cteva dialoguri predefinite pe care le putei invoca n aplicaii.


Dialogurile sunt forme. Cnd n Notepad sau Microsoft Word acionai F ile ->
O p e n , F ile -> S a v e A s sau F ile -> P a g e S e tu p , invocai de fapt unul dintre
dialogurile standard Windows.
Clasele .N E T care reprezint dialogurile predefinite sunt: M e s s a g e B o x ,
O p e n F ile D ia lo g , S a v e F ile D ia lo g , F o n tD ia lo g , C o lo r D ia lo g , P a g e S e tu p D ia lo g ,
P r in tD ia lo g i P rin tP re v ie w D ia lo g .
Toate aceste dialoguri sunt d ia lo g u ri m o d a le .

Descrierea dialogurilor predefinite

M e s s a g e B o x este cel mai comun dialog prdfinit. Clasa definete metoda


static Show () n mai multe versiuni. Cea mai simpl versiune, cu un singur
parametru, a fost deja folosit n aceast lucrare. n exemplu se apeleaz o
metod show ( ) cu patru parametri:

MessageBox.Show("Copierea nu a putut fi realizat!",


"Eroare de copiere",
MessageBoxButtons.RetryCancel,
MessageBoxIcon.Exclamation);

Efectul pe ecran este :

Eroare de copiere

Copierea nu a putut fi realizat!

Retry Cancel

Icon-urile pe care le poate afia un message box sunt:


178 Partea a Il-a . P rogram are W indow s cu V isual C # Express Edition

A s te ris c , E rro r, E x c la m a tio n , H a n d , In fo rm a tio n , N o n e , Q u e s tio n , S to p i


W a rn in g . Acetia sunt membrii ai enumerrii MessageBoxicon, iar semnificaiia
lor este evident.
B u to a n e le pe care le poate afia un message box sunt: A b o r tR e try lg n o re
(3 butoane), O K , O K C a n c e l (2 butoane), Y e s N o (2 butoane), Y e s N o C a n c e l (3
butoane). Aceste entiti sunt membri ai enumerrii MessageBoxButtons.
n aplicaia pe care o vom realiza n cadrul temei M D I - M u ltip le D o cu m e n t
Interface vom arta cum dai funcionalitate butoanelor de pe form.

O p e n F ile D ia io g motenete clasa F ile D ia io g . Dialogul (forma) este o


instan a clasei. Permite utilizatorului s selecteze un fiier pentru a fi deschis.
Atenie, dialogul nu deschide fiierul! Acest lucru cere un mic efort de programare,
aa cum vom vedea n subcapitolul urmtor. Numele fiierului selectat se atribuie
n mod automat proprietii F ile N a m e . Formatul fiierelor care trebuie deschise se
stabilesc cu ajutorul proprietii F ilte r.

S a v e A s D ia lo g motenete clasa F ile D ia io g . Dialogul este folosit n scopul


alegerii unei locaii pentru salvarea unui fiier. Dialogul nu salveaz fiierul.
Numele fiierului selectat se atribuie n mod automat proprietii F ile N a m e . Clasa
poate crea un nou fiier sau poate suprascrie unul existent.

F o n tD ia lo g deriv din clasa C o m m o n D ia lo g . Utilizatorul poate alege un


font dintre cele instalate pe calculator prin simpla selectare cu mouse-ul.

P a g e S e tu p D ia io g are ca i clas de baz direct C o m m o n D ia lo g .


Utilizatorul poate stabili setri pentru pagin, cum ar fi marginile, formatul, etc.

P rin tD ia lo g deriv din clasa C o m m o n D ia lo g . Dialogul permite alegerea


unei imprimante, setarea formatului de imprimare, alegerea unei poriuni de
document care va fi printat i invocarea imprimantei.

P r in tP r e v ie w D ia lo g este derivat din clasa F o rm . Dialogul permite


examinarea unui document nainte de imprimare.

in d ic a ie :
Alegei un utilitar, cum este M icrosoft Word i revedei toate aceste dialoguri,
accesndu-le pe rnd din meniul F ile . Merit s o facei, pentru c acum le vedei
cu ochii programatorului.

Afiarea dialogurilor predefinite

Dialogurile standard Windows sunt forme .NET. n plus, sunt dialoguri


modale. Aadar, afiarea lor se face cu ajutorul metodei S h o w D ia Io g ():

E x e m p lu :

lat cum afiai dialogul O p e n F ile D ia io g :


C apitolul 7. C ontroalele W indows F orm s 179

if (openFileDialog.ShowDialog() =
System.Win d o w s .F o r m s .DialogResult.OK)
{
// Cod care deschide fiierul
}

openFileDialog este o referin la un obiect de tipOpenFileDialog. Referina


se creaz n mod automat n momentul n care din Toolbox alegei un control
OpenFileDialog i l plasai pe suprafaa formei.
Valoarea de retur a metodei este egal cu unul dintre membrii enumerrii
DialogResult. Acetia sunt: OK, Cancel, Abort, Retry, None, Ignore, Yes, No.
Fiecreia dintre aceste valori i corespunde un buton pe suprafaa dialogului. n
mod implicit, dialogurile predefinite afieaz butoanele OK i Cancel, ns prin
setarea proprietilor corespunztoare ale dialogului, le putei afia i pe celelalte.
Codul de mai sus se interpreteaz astfel: ShowDialogO afieaz dialogul
OpenFileDialog. Dac utilizatorul apas butonul OK, atunci se execut codul
dintre acolade. Ce anume trebuie s scriei, vom vedea la seciunea Controlul
RichTextBox.
Pentru afiarea celorlalte controale predefinite, se procedeaz similar, cu
singura diferen c vei nlocui referina openFileDialog cu una dintre
referinele: saveFileDialog, printDialog, pageSetupDialog, etc.

Observaie:
Toate cele apte dialoguri predefinite sunt d ia lo g u ri modate, deoarece
utilizeaz metoda ShowDialogO. Un dialog modal ntrerupe aplicaia, iar
utilizatorul nu poate continua pn n momentul n care dialogul a fost nchis.

Aplicaia DialoguriPredefinite
Proiectul pe care l propunem este o aplicaie cu un meniu din care
utilizatorul poate selecta opiuni de deschidere a dialogurilor predefinite. Pentru
unele dialoguri, se va scrie i cod suplimentar, mai ales referitor la setarea
proprietilor. Vestea bun este c vei scrie ntotdeauna aproape la fel atunci cnd
lucrai cu dialoguri predefinite.

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


DialoguriPre definite.

2. Din Toolbox plasai cu ajutorul mouse-ului un control MenuStrip pe


suprafaa formei.

3. Creai un prim meniu numit Fiier, cu opiunile Deschide, Salveaza ca,


Setare pagina, Imprimare i Previzualizare:
180 P artea a II-a. P rogram are W indow s cu V isual C# E xpress E dition

sier. |[ Eormat

Deschide
Salveaza ca
Setare pagina
Imprimare
Previzualteare

4. Creai un al doilea submeniu numit Format, cu opiunile Font i Culori:

|R*I
B ie r ' | Format |

1 Font

1 gulori

1 ' -

5. Din Toolbox plasai pe suprafaa formei urmtoarele controale:


OpenFileDialog, SaveFileDialog, PageSetupDialog, PrintDialog,
PrintPreviewDialog, PrintDocument, FontDialog, ColorDialog. n "tray-
ul designerului de forme vei remarca imediat referinele la aceste obiecte,
care au fost adugate n cod.

6. n continuare vei trata evenimentul Click pentru fiecare dintre opiunile


meniului. Facei dublu click pe opiunea Deschide. n handter-ui
evenimentului, scriei codul:

private void deschideToolStripMenuItem_Click


(object sender, EventArgs e)
{
// Titlul dialogului
openFileDialogl.Title = "Deschide Fiier";

// Seteaz tipurile de fiiere care apar


// n combobox-ul "Files of Type"
openFileDialogl.Fiiter =
"Fiiere R i c h Text (*.rtf)|*.rtfjFiiere Text (*.txt)|*.t x t " ;

/ / n combobox-ul File Name nu vrem s apar la


// deschiderea dialogului nici un nume de fiier
openFileDialogl.FileName = "";
C apitolul 7. C ontroalele W indows F orm s 181

// Directorul care se deschide n mod implicit


openFileDialogl.InitialDirectory = "MyDocuments";

// Afieaz o atenionare dac utilizatorul


// specific un fiier care nu exist
openFileDialogl.CheckFileExists = true;

// Deschide dialogul OpenFileDialog


if (openFileDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Cod care deschide fiierul
1

7. Dublu click pe opiunea Salveaz ca. n metoda de tratare, scriei:

private void salveazaCaToolStripMenuItem_Click


(object sender, EventArgs e)
I
// Titlul dialogului
saveFileDialogl.Title = "Salveaza Fiierul";

// Extensia implicit de salvare a fiierelor


saveFileDialogl.DefaultExt = .rtf ;

// Atenionare dac ncercai s suprascriei


saveFileDialogl.OverwritePrompt = true;

// Deschide dialogul SaveFileDialog


if (saveFileDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Cod care salveaz fiierul
}

8. Dublu click pe opiunea Setare pagina. n metoda de tratare, scriei:

private void setarePaginaToolStripMenuItem_Click


(object sender, EventArgs e)
{
/ / S e preiau setrile din printDocumantl
pageSetupDialogl.Document = printDocumentl;

// Setrile de pagin
pageSetupDialogl.PageSettings =
printDocumentl.DefaultPageSettings;
182 Partea a II-a. P rogram are W indow s cu V isual C# E xpress E dition

// Diverse seciuni ale dialogului devin active sau


// inactive. De fapt, valoarea implicit a acestor
// proprieti este true
pageSetupDialogl.AllowMargins = true;
pageSetupDialogl.AllowPaper = true;
pageSetupDialogl.AllowOrientation = true;
pageSetupDialogl.AllowPrinter = true;
pageSetupDialogl.ShowNetwork = t r u e ; '
pageSetupDialogl.EnableMetric = false;
pageSetupDialogl.ShowHelp = false;

// Se deschide dialogul i se preiau setrile


// de pagin n obiectul de tip PrintDocument
if (pageSetupDialogl.ShowDialog() ==
System.Windows.F o r m s .DialogResult.OK)
printDocumentl.DefaultPageSettings =
pageSetupDialogl.PageSettings;
!
9. Facei dublu click pe opiunea Im prim are. n handler scriei codul:

private void imprimareToolStripMenuItem_Click


(object sender, EventArgs e)
{
/ / S e preiau setrile de printare din
// obiectul de tip PrintDocument
printDialogl.Document = printDocumentl;

/ / S e deschide dialogul PrintDialog


if (printDialogl.ShowDialog() =
System/Windows.F o r m s .DialogResult.OK)
{
// Starteaz procesul de printare
printDocumentl.P r i n t () ;

// Cod care transform documentul


/ / n imagine i l printeaz
// . . .
}
}
10. Dublu click pe opiunea Previzualizare. n handler, scriei codul:

private void previzualizare?oolStripMenuItem_Click


(object sender, EventArgs e)
{
if (printPreviewDialogl.ShowDialog() ==
System.Windows.F o r m s .DialogResult.OK)
{
// Cod care afieaz documentul n dialog
}
C apitolul 7. C ontroalele W indows Form s ]83

11. Dublu click pe opiunea Font. n handler-u\ evenimentului, scriei codul:

private void fontToolStripMenuIteml_Click


(object sender, EventArgs e)
(
//' Se deschide dialogul FontDialog
if (fontDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
1
// Cod care reafieaz documentul cu
// fontul ales de utilizator
}
I

12. Dublu click pe opiunea C ulori. n handler-ul evenimentului, scriei codul:

private void culoriToolStripMenuItem_Click


(object sender, EventArgs e)
{
// Se deschide dialogul ColorDialog
if (colorDialogl.ShowDialog() ==
System.Windows.F orms.DialogResult.OK)
{
// Cod care actualizeaz culorile in document
}
}

13. Compilai i rulai cu F5.

8 asie cokxs;


r i B l I H I


i l i e i F i r
Custom colors:



Define Custom Colors
184 Partea a Il-a . Program are W indow s cu V isual C # E xpress Edition

Comentarii:
Proprietatea Filter este comun dialogurilor O penF ileD ialog i
S aveA sD ialog, ntruct este motenit de la clasa de baz comun,
FileDialog. Caracterul ' | ' (pipe) delimiteaz tipurile de fiiere pe
care le putei selecta, dar i intrrile n combobox : "Fiiere Rich
Text (*.r t f ) 1*.rtf|Fiiere Text (*.txt)|*.tx t " ;

Files of type: \ Fiiere Rich I ex* f.rtf) v ; | Cancel


---------------- jfflEHiHaBaM
1Fiiere TexHMxfl

Dialogurile predefinite se afieaz cu metoda S h o w D i a l o g O , iar tipul


de retur al acestei metodei se analizeaz pentru a vedea dac
utilizatorul dorete s pstreze setrile pe care le-a fcut sau vrea s
renune la ele.
Reinei c OpenFileDialog nu deschide un fiier (document) ci numai
v permite s-l alegei. Pentru deschidere avei nevoie de un control
suplimentar, capabil s afieze coninutul fiierului, aa cum este un
T e xtB o x sau un R ichTextB ox. Aceleai consideraii sunt valabile i
pentru celelalte dialoguri predefinite.

Not:
n ce privete printarea efectiv a unui document, aceasta se face prin
apelul metodei Prin () a clasei PrintDocument. Ciasa PrintDocument este
definit n spaiul de nume S yste m .D ra w in g .P rin tin g . Obiectul de tip
PrintDocument preia setrile de pagin stabilite de ctre utilizator n dialogul
PageSetupDialog, i trimite documentul la imprimant. Codul necesar poate fi
gsit n documentaia clasei P rin tD o cu m e n t sau n articole din MSDN {Microsoft
Developer Network).

Sfat practic
S avei n permanen deschis Helpul mediului integrat. Acolo gsii
imediat clasele cu care lucrai, cu descrierea complet a cmpurilor,
proprietilor, m etodelor i evenimentelor lor, dar i cu exemple de cod care v
pot ajuta. Vei descoperi foarte repede membrii a i claselor care v p o t fi utili.
Reamintim locaia B ib lio te c ii de Clase: Help -> C o n te n ts -> .NET
Fram ew ork S D K -> .N E T F ra m e w o rk C lass Library.

M D I - M ultip le D o c u m e n t Interface

O aplicaie MDI se lanseaz cu o singur fereastr container care reprezint


ntreaga aplicaie.
C apitolul 7. C ontroalele W indows F orm s 185

n interiorul ferestrei container se pot deschide multiple ferestre chifd.


Gndii-v la M icrosoft Word. Ferestrele interioare reprezint diferite documente pe
care utilizatorul le poate edita n acelai timp sau diferite vederi ale acelorai date.

Aplicaiile MDI difer de cele de tip SDI (Single document interface) prin
aceea c SDI au o singur fereastr copil. Notepad este un asemenea exemplu.
Dac dorii s editai dou documente, trebuie s deschidei dou instane
Notepad.

Att fereastra printe ct i ferestrele copil sunt de fapt forme .NET. O form
devine container n momentul n care proprietatea isMdiContainer este setat
true.

Aplicaia MdiExam ple

Aplicaia implementeaz:

> Deschiderea i nchiderea ferestrelor child.


> Minimizarea i maximizarea ferestrelor.
> Aranjarea ferestrelor.
> Tratarea mesajului de atenionare la ieirea din aplicaie.

Urmai paii:

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


MdiExample.

2. Setai forma ca i container MDI. Pentru aceasta, n fereastra P ro p e rtie s


atribuii proprietii IsMdiContainer valoare true.

3. Din Toolbox plasai cu ajutorul mouse-ului un control MenuStrip pe


suprafaa formei.

4. Creai un prim meniu numit File, cu opiunile New, Minimize, Maximize,


Close, Close AII i Exit. Creai un al doilea meniu cu numele Window,
avnd opiunile: Tile i Cascade:
186 P a rtea a II-a . P r o g r a m a r e W in d o w s cu V isu a l C # E x p ress E d itio n

5. Adugai n clasa F o rm l un cmp privat care contorizeaz numrul de


ferestre copil i o metod privat care creeaz o fereastr copil. Pentru
aceasta, acionai dublu click pe numele formei n S o lu tio n E xplorer. n
fiierul F o rm l.cs, n clasa Forml, scriei codul:

private int nr = 0; // Numrul de ferestre child

private void CreateChildf)


{
// Crem o forma child.
Form f = new Form();
nr++ ;

// Textul din bara de titlu


f.Text = "Documentul " + nr;

// Forma f devine document child


// this este referin la forma container
f.MdiParent = this;

// Afieaz forma child


f .S h o w ();
}

6. La pornirea aplicaiei, dorim s se deschid o fereastr copil. Tratm


evenimentul Load generat la ncrcarea formei. Dublu click pe suprafaa
formei. n metoda de tratare a evenimentului, scriei:

private void Forml_Load(object sender, EventArgs e)


C apitolul 7. Controalele W indows F orm s UI

{
C r e a t e C h i l d ();

7. Acum tratm evenimentele C lick pentru toate opiunile din meniuri.


Acionai dublu click pe opiunea New. n metoda de tratare, scriei:

private void newToolStripMenuItem_Click(object sender,


EventArgs e)
{
// Dac nu exist ferestre copil active
// setm contorul la 0
if (ActiveMdiChild = nuli)
nr = 0 ;
C r e a t e C h i l d ();
}

8. Acionai dublu click pe opiunea M inim ize. n metoda de tratare, scriei:

private void minimizeToolStripMenuItem_Click(


object sender, EventArgs e)
{
// Dac exist o fereastr copil activ,
// aceasta se minimizeaz
if (ActiveMdiChild != nuli)
A ctiveMdiChild.Windowstate =
F o r m W i n d o w S t a t e .Minimized;

9. Acionai dublu click pe opiunea Maximize. n metoda de tratare, scriei:

private void minimizeToolStripMenuItem_Click(


object sender, EventArgs e)
{
// Dac exist o fereastr copil activ,
// aceasta se maximizeaz
if (ActiveMdiChild != nuli)
ActiveMdiChild.Windowstate =
FormWindowState.Maximized;

10. Acionai dublu click pe opiunea Close. n metoda de tratare, scriei:

private void closeToolStripMenuItem_Click(


object sender, EventArgs e)
{
// nchide fereastra copil activ
if (ActiveMdiChild != nuli)
A c t i v e M d i C h i l d . C l o s e () ;
}
188 Partea a Il-a . Program are W indow s cu V isual C# E xpress Edition

11. Acionai dublu click pe opiunea C lose A I I . n metoda de tratare, scriei:

private void closeallToolStripMenuItem_Click(


object sender, EventArgs e)
{
// nchide pe rnd fiecare form copil
foreach (Form f in thi s .MdiChildren)
f.Close();
}

12. Acionai dublu click pe opiunea Exit. n metoda de tratare, scriei:

private void exitToolStripMenuItem_Click(object sender,


EventArgs e)
(
Application.Exit(); // Ieire din aplicaie
}

13. Acionai dublu click pe opiunea Tile . n metoda de tratare, scriei:

private void tileToolStripMenuItem_Click(object sender,


EventArgs e)
(
// Aranjare Tile pe orizontal
t h i s .LayoutMdi(MdiLayout.TileHorizontal);
}

14. Acionai dublu click pe opiunea Cascade . n metoda de tratare, scriei:

private void tileToolStripMenuItem_Click(object sender,


EventArgs e)
{
// Aranjare n cascad
t h i s .LayoutMdi(MdiLayout.Cascade);
1

15. La nchiderea formei, dorim s apar un message box cu butoanele Yes i


No, care s ne ntrebe dac suntem siguri c vrem s ieim. n Form
Designer selectai forma container. n fereastra P ro p e rtie apsai butonul
Events (fulgerul). Acionai dublu click pe evenimentul F o rm C lo sin g . n
metoda de tratare a evenimentului, scrii codul evideniat n B old:

private void Forml_FormClosing(object sender,


FormClosingEventArgs e)
{
DialogResult result = MessageBox.S h o w (
"Esti sigur ca vrei sa parasesti aplicaia?",
"Avertizare", MessageBoxButtons.X esNo,
MessageBoxIcon.Question);
C apitolul 7. C ontroalele W indows F orm s 189

// Dac s-a apsat No, atunci aplicaia


// nu se nchide
if (result = DialogResult.No)
e .Cancel = tru e ;

16. Compilai i rulai aplicaia cu F5.

Cteva ca p tu ri de ecran d in tim p u l ru l rii:

a) Dup deschiderea ctorva ferestre copil:

b) Aranjare T ile :

Aplicaie MOI
190 P artea a Il-a . P rogram are W indow s cu V isual C # E xpress Edition

c) La ieirea din aplicaie:

De reinut:

O form devine container MDI dac se seteaz tr-ue valoarea propietii


IsMdiContainer.
Ferestrele child se construiesc ca oricare alt form, dup care
proprietatii MdiParent i se atribuie o referin la forma printe:

Forra f = new Form();


f.MdiParent = this;
f .S h o w ();

Proprietatea MdlChildren a formei container reine referine ia toate


formele copil.
Proprietatea ActiveMdiChild returneaz o referin la fereastra child
activ.
Proprietatea WindowState a unei forme seteaz starea curent a
ferestrei. n mod implicit, valoarea ei este Normal. Se mai pot seta valorile
Maximized i Minimized. Aceste valori se obin prin accesarea membrilor
enumerrii: FormWindowState. Exemplu:

ActiveMdiChild.WindowState = FormWindowState.Maximized;

Metoda a LayoutMdi) a clasei Form, aranjeaz formele copil MDI n


forma printe.
Metoda show) a clasei MessagBox este suprancrcat. Una dintre
versiuni, cea din aplicaie, are trei parametri: textul mesajului, textul din
bara de titlu i butoanele care trebuie s apar pe form. Reamintim c un
message box este un dialog predefinit Windows, deci o form, care
C apitolul 7. C ontroalele W indows F orm s 191

returneaz ntotdeuana o valoare de tip DialogResult. Aplicaia arat


cum putei exloata valoarea returnat.
* La tratarea evenimentului FormClosing, unul dintre parametri este tipul
FormClosingEventArgs. Clasa are proprietatea Cancel. Dac valorea
acestei proprieti este true, atunci evenimentul nu se mai declaneaz,
deci forma nu se mai nchide (scriei e .Cancel = trua);

Probleme propuse:

Implementai aplicaiei MdiExample facilitatea de aranjare a ferestrelor n


modul Tije, dar pe vertical.
* Adugai aplicaiei MdiExample un control T o o lS trip , cu butoane cu
aceeai funcionalitate cu cea a opiunilor meniului.
* Integrai ferestrelor copil n aplicaia MdiExample un control de tip
T extB ox, pentru ca aplicaia s funcioneze ca editor de text.

C ontrolu l R ich T extB o x

R ich T extB ox deriv direct din clasa TextB oxB ase, la fel ca i T extB ox. n
vreme ce un T e xtB o x se utilizeaz pentru a introduce secvene scurte de
caractere de la tastatur, un R ich T e xtB o x se utilizeaz cu precdere ca editor de
text.
Controlul are toate facilitile unui TextB ox, dar ofer i altele, cum sunt
posibilitatea de formatare a fontului (Italic, Bold, Underline! i a paragrafului. Textul
se poate introduce de ctre utilizator, poate fi ncrcat din fiiere de tip RTF (Rich
Text Format) sau din fiiere text. Clasa are metode pentru deschidere i pentru
salvare de fiiere n aceste formate. Un control de tip T e x tB o x poate fi nlocuit fr
modificri majore de cod cu un control R ichTextB ox.
n aplicaia care urmeaz vom utiliza pentru prima oar i o bar de
instrumente, cu ajutorul controlului T o o lS trip . nainte de a continua, cteva cuvinte
despre acest control:

Controlul ToolStrip

Este un control care v permite s creai bare de instrumente. Este de fapt


un container pentru butoane standard Windows, lat un exemplu:

i Normal + Arial, - Arial 10 j. B I ! s : = rs * fc r - ^ i *

Se pot crea bare de instrumente cu tem sau fr tem, cu aparena i


comportamentul barelor Micosoft Office, sau Internet Explorer, dar si bare cu stil i
comportament stabilit de dumneavoastr. Clasa T o o lS trip abund de surpize
plcute. Merit s le explorai.
192 Partea a Il-a . Program are W indow s cu V isual C# E xpress Edition

Aplicaia RichTextBoxExample
Vom realiza un mic editor de text, asemntor celui creat n subcapitolul
TextBox. Controlul care afieaz textul va fi de data aceasta un R ichT extB ox.
Aplicaia va avea un meniu, faciliti de deschidere i salvare a documentelor n
format RTF, ca i posibilitatea de a seta fontul i culoarea lui. Evident, pentru
implementarea acestor faciliti, vom utiliza dialoguri predefinite.

1. Creai un proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


RichtextBoxExample. Selectai forma i din fereastra P ro p e rtie s atribuii
proprietii T ext valoarea: "Editor de fiiere R TF.

2. Din T o o lb o x plasai cu ajutorul mouse-ului un control M e n u S trip pe


suprafaa formei.

3. Creai un prim meniu numit Fiier, cu opiunile Nou, D eschide, Salveaza


Ca, i Ieire. Creai un al doilea meniu cu numele Form at, avnd opiunile:
F ont i C uloare:

S S E d ito r d e f i ie r e R T F

i l| Fiier l| - E o r m a t ' i

Nou
'1 deschide l

3 alveaza Ca i

"a Ie s 're
;...... T ir '

4. Din T o o lb o x plasai pe form cu ajutorul mouse-ului un control T o o lS trip .


C apitolul 7. C ontroalele W indows F orm s 193

5. n controlul T o o lS trip adugai pe rnd 9 butoane din lista controlului, aa


ca n figura de mai sus. Rolul acestor butoane poate fi descris prin textele:
Fiier Nou, Deschide Fiierul, Salveaz F iie ru l', Decupeaz",
Copiaz , Lipete , Alege un F o n f, "Alege o Culoare", Bullets. Practic
au exact funcionalitatea opiunilor din meniu.

6. Pe fiecare buton adugat, vom prefera s lipim cte o imagine, dect s


scriem text. Cutai pe Internet cteva imagini .jp g sau .g if adecvate i
salvai-le ntr-un folder oarecare. Selectai controlul T o o lS trip i din
fereastra P rop e rtie s setai proprietatea Im ageS calingS ize la valorile 20 i
20 (implicit e 16 i 16). Aceasta, pentru a mri puin dimensiunile imaginilor
afiate pe butoane.

7. Click drept pe fiecare buton din T o o lS trip i alegei Set Image. n dialogul
S elect R esource, apsai butonul Im p o rt. Vei lipi astfel pe fiecare buton
imaginea dorit:

Editor de fiiere RTF


- f i ie r Eorrrtat

& >,S iz ] ' View Code

I j j ; :Set image.,. - ,
Enabled

8. Dorim s atam fiecrui buton cte un Tool Tip Text, adic un mic text
care apare cnd staionai o clip cu mouse-ul asupra butonului. Pentru
aceasta, selectai pe rnd cte un butorn i din P ro p e rtie s atribuii
proprietii T ext un text scurt, reprezentnd rolul butonului:

Editor de fiiere RTF 0


i p e r -fVormaf ^ . 7 v-i''y , <

IAlege un Font^

9. Luai din T o o lb o x un control R ich T e xtB o x i plasai-l pe suprafaa formei.


Acionai click pe sageata din colul dreapta sus a controlului i alegei
Dock in parent container.

10. Vom trata evenimentul C lic k pentru fiecare dintre opiunile meniului, dar i
pentru butoanele din T o o lS trip . Dublu click pe opiunea Nou. n corpul
handler-ului de eveniment, scriei codul:
194 P artea a I l-a . P rogram are W indow s cu V isual C# E xpress E dition

private void nouToolStripMenuItem_Click(object sender,


EventArgs e)
{
// terge textul controlului
richTextBoxl.Text = "";
}

Dublu click pe butonul cu textul Fiier Nou i scriei acelai cod.

11. Facei dublu click pe opiunea Deschide. Corpul handler-ului trebuie s


conin exact acelai cod scris n aplicaia Dialoguri Predefinite din
subcapitolul precedent. Precizm doar codul suplimentar:

if (openFileDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Metoda LoadFile() deschide fiierul
richTextBoxl.LoadFile(openFileDialogl.FileName);
}

Dublu click pe butonul cu textul Deschide F iie ru l. Scriei acelai cod.

12. Dublu click pe opiunea de meniu Salveaza Ca. Corpul handler-ului trebuie
s conin exact acelai cod scris n aplicaia Dialoguri Predefinite din
subcapitolul precedent. Precizm doar codul suplimentar:

if (saveFileDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Metoda SaveFile() salveaz pe disc textul
// controlului ntr-un fiier cu formatul RTF
richTextBoxl.SaveFile(saveFileDialogl.FileName,
RichTextBoxStreamType.RichText);

>

Dublu click pe butonul cu textul Salveaz F iierul. Scriei acelai cod.

13. Dublu click pe opiunea Ieire. n corpul riancf/er-ului adugai codul:

Application.Exit(); // Ieire din aplicaie

14. Dublu click pe opiunea de meniu Font. Handler-ul evenimentului trebuie


s arate astfel:

private void fontToolStripMenuItem_Click(object sender,


EventArgs e)
(
if (fontDialogl.ShowDialog() ==
C apitolul 7. Controalele W indows F orm s 195

System.Windows.Forms.DialogResult.OK)
{
// Poriunea selectat din text preia
// caracteristicile alese de ctre utilizator
richTextBoxl.SelectionFont =
fontDialogl.F o n t ;
}
}

Dublu click pe butonul cu textul Alege un F o n f. Scriei acelai cod.

15. Dublu click pe opiunea de meniu C uloare. Handler-ul evenimentului


trebuie este:

private void culoareToolStripMenuItem_Click


(objectsender, EventArgs e)
I
if (colorDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
richTextBoxl.SelectionColor =
colorDialogl.C o lor;
}
}

Dublu click pe butonul cu textul Alege o Culoare". Scriei acelai cod.

16. Selectai ultimul buton din T o o lS trip , cu textul Bullets". n fereastra


P roperties, setai proprietatea Name la valoarea bulletButton" i
proprietatea CheckOnClick la valoarea true. Dublu click pe buton
pentru a trata evenimentul C lick. n metoda handler scriei:

private void toolStripButton9_Click(object sender,


EventArgs e)
I
// Dac butonul era apsat atunci textului
// selectat nu i se aplic stilul bullet
if ( bulletButton.Checked )
richTextBoxl.SelectionBullet = false;
else
richTextBoxl.SelectionBullet = t r u e ;

17. Compilai i lansai cu F5.


196 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress Edition

Editor de fiiere RTF

Spune-mi,daca te-as prinde intr-o zi


Si ti-as saruta talpa piciorului
Nu-i asa ca ai schiopata puin dupa aceea
De frica sa nu-m i striveti srutul?

Font: Font style: Size:


Microsoft Sans SeriJ 1 i Italic 14
i__________ ______! i .._.pK...J
i p r a B w a i A ' 1Regular___________ ! xi j
Milano LET i s ~ s I Cancel
i Fh MisterFarl RT ! i Rnlri i 1R I

Observaie:
r
Editorul de mai sus lucreaz numai cu Fiiere R T F . La ncercarea de
deschidere a unui alt tip de fiier, aceast versiune a metodei
L o a d F i l e O arunc o excepie. Din acest motiv, ntr-o aplicaie
serioas, vei apela asemenea metode numai n interiorul blocurilor try/
catch:

try
{
richTextBoxl.LoadFile(openFileDialoal.FileName);
}
catch (System.Exception e)
{
MessageBox.Show(e.Message) ;
}

Exist o a doua versiune a acestei metode care are doi parametri i


poate fi adaptat la lucrul cu fiiere text.
Clasa R ic h T e x tB o x are i alte faciliti de editare i formatare a textului,
pe care le putei explora de exemplu, mbuntind editorul de mai sus.

Controlul ToolTip

T o o lT ip se utilizeaz pentru afiarea unor mesaje de informare sau de


avertizare, atunci cnd utilizatorul plaseaz cursorul desupra unui control. O
C apitolul 7. C ontroalele W indows F orm s 197

singur instan a clasei este suficient pentru a furniza texte de informare pentru
toate controalele unei forme.

Exemplu:
ToolTip t = new Tool T i p O ;
Button b = new Bu t t o n ();
ComboBox c = new ComboBox();
t.SetToolTip(b, "Valideaza datele");
t.SetToolTip(c, "Lista elevilor din clasa a Xll-a B " ) ;

Dac dorii stiluri i afiri diferite pe aceeai form, vei utiliza mai multe controale
T o o lT ip .

Principalii membri ai clasei ToolTip

P ro prie ti :

AutoPopDelay - Returneaz sau seteaz perioada de timp n care T o o lT ip


rmne vizibil dac cursorul e staionar deasupra
controlului.
IsBallon - Returnez o valoare de tip b o o l care indic-dac mesajul
este inlclus ntr-o fereastr balon.
ToolTipIcon - Seteaz un icon pentru T o o lT ip .
ToolTipTitle - Stabilete un titlu pentru T o o lT ip

M e to d e :

H i d e () - Ascunde fereastra T o o lT ip
S h o w () - Seteaz un text pentru T o o lT ip i l afieaz
RemoveAll{) - nltur toate textele asociate cu un control T o o lT ip

E v e n im e n te :

Popup Se declaneaz nainte ca T o o lT ip s fie afiat

Aplicaia ToolTipExample
n proiectul de fa se folosete acelai T o o lT ip pentru mai multe controale
de pe aceeai form. Se utilizeaz designer-ul pentru toate aciunile necesare.

1. Creai un proiect de tip W indow s F o rm s A p p lic a tio n cu numele


ToolTipExample.
198 P artea a Il-a . P rogram are W indow s cu V isual C# E xpress Edition

2. Din Toolbox plasai pe form cteva controale: dou controale de tip


TextBox, un GroupBox, dou controale de tip RadioButton, un
CheckBox i dou butoane:

Nume:

Adresa

Studii

O Medii

O Superioare OK

O Cstorit
Cancel

3. Din ToolBox alegei un ToolTip i plasai-l pe suprafaa formei. Acesta nu


este vizibil pe form, dar referina toolTipl apare n designer tray.

4. Selectai primul control TextBox. n fereastra Properties selectai ToolTip


on to o lT ip l. Acionai click pe sgeata din dreapta i n panoul care se
deschide introducei mesajul: Introducei numele, iniiala tatlui i
prenumele". Apoi acionai Ctrl + Enter.

5. Selectai al doilea control TextBox. Acionai de aceeai manier ca la


pasul 4, dar introducei alt mesaj, cum ar fi Introducei strada, numrul
locuinei i localitatea".

6. Se repet pasul 4, pentru controalele de tip RadioButton, pentru


CheckBox i pentru cele dou controale de tip Button.

7. Compilai i rulai cu F5.


La rulare, cnd staionai cu mouse-ul asupra fiecrui control, apar mesajele
ToolTip:

Nume: Nume: j
~j Introducei numele, iniiala tatlui i prenumele
Adresa; Adresa: [

Studii ' Studii


O Medii O Medii
O Supe/ioate OK Superioare OK

O Cstorit
Cancel
Qasalonf .... . ----------------
{lice n , m a ste ra t s a u d o c to ra t \
C apitolul 7. C ontroalele W indows F orm s 199

De retinut:
i

> Mesajele T o o lT ip se pot seta att design time, ct i run time.


> Se poate introduce ToolT ip fr ajutorul des/gner-ului. Tratai de exemplu
evenimentul Load pentru forma acestei aplicaii (dublu click pe suprafaa
formei) i introducei codul:

private void Forml_Load(object sender, EventArgs e)


{
ToolTip t = new ToolTip ();
t .SetToolTip(textBox2,
"Introducei numele, iniiala tatlui i prenumele");
t .SetToolTip(textBoxl,
"Introducei strada i numrul locuinei");
t .SetToolTip(radioButtonl,
"Studiile postliceale sunt considerate medii");
t .SetToolTip(radioButton2,
"Licen, masterat sau doctorat");
t .SetToolTip(checkBoxl,
"Nu bifai n cazul in care suntei divorat!");
t .SetToolTip(buttonl,
"Se valideaz datele introduse");
t .SetToolTip(button2,
"Se renun la datele introduse");
)

C o n tro lu l N o tify lc o n

Formele, ca de altfel i alte controale, motenesc metoda Hide() de la


clasa Control. Dac utilizatorul ascunde forma principal a aplicaiei, atunci nu
mai are posibilitatea s o reafieze.
Clasa Notifylcon ofer posibilitatea de a accesa procese care ruleaz n
background. Creeaz un icon n zona de notificare (notify area) din system tray.
Zona de notificare se gsete n dreapta task bar-ului, lng ceas. Iconul rspunde
la evenimente, cum sunt C lick sau D o u b le c lic k pe care le putei trata pentru a
reafia fereastra aplicaiei. Alternativ, se obinuiete s se ataeze un meniu
contextual care se deschide la click drept pe icon.

Principalii membri ai clasei

P rop rieti :
ContextMenu - Returneaz sau seteaz un meniu de context pentru icon
Icon - Returneaz sau seteaz un iconul controlului
Text - Returneaz sau seteaz un text ToolTip. cnd cursorul
mouse-ului staioneaz deasupra iconului
Visible - Stabilete dac iconul e vizibil n zona de notificare

200 P artea a Il-a . Program are W indow s cu V isual C# E xpress Edition

Metode:

ShowBallonTiprf) Afieaz mesajul ToolTip ntr-o form asemntoare


unui balon

Evenimente:

C lic k - Se declaneaz la click pe icon


D o u b l e c l i c k ______ - Se declaneaz la dublu click pe icon

Aplicaia NotifylconExample Jg
Vtf
Pe o form plasm un buton care la click o ascunde. Folosim un Notifylcon |
pentru reafiarea formei. Reafiarea se produce la dublu click pe icon sau la ciick fj
ntr-un meniu de context. jfi

Urmai paii: i|p

1. Creai un proiect de tip W indow s F o rm s A p p lic a tio n cu numele |J i


NotifylconExample. - r

2. Din Toolbox plasai pe form un control de tip Button. n fereastra


Properties setai proprietea Text la valoarea Ascunde Forma:

Acunde Forma

3. Tragei deasupra formei un control de tip ContextMenuStrip. Selectai n jp


designer tray referina contextMenuStripl. Introducei itemii Acunde i V
Reafiseaza: ~

I-
C apitolul 7. C ontroalele W indows F orm s 201

Tragei deasupra formei un control de tip N o tify lc o n . Selectai in designer


tray referina notifyiconl.
a. n fereastra P roperties, selectai proprietatea Text i introducei
textul care dorii s apar ca tool tip cnd staionai cu mouse-ul
deasupra iconului.
b. Setai proprietatea Visible la true.
c. Selectai proprietatea ic o n i alegei iconul care apare n zona de
notificare. Evident, trebuie s avei unul pregtit. Nu uitai s setai
un icon. n lipsa iui, nu apare la execuie nimic n notify area.
d. Selectai proprietatea ContextMenuStrip i alegei valoarea
contextMenuStrip 1.

Properties;^:

n o t i f y l c o n S y ste m .W in d o w s.Fo rm s.N o tifylc o n

jj] / :M
(A pp licatio n Settin gs)
(Name) n o t if y ic o n l
8 ailoon Tip Icon N on e
BalloonTipText
BalloonTipT'itle
S C on te x tM e n u Strip c o n te x tM e n u S trip 1
G e n e ra te M e m b e r True
S| I P S l (Ic o n ) Qi
M odifie rs P rivate
Tag
T e xt C lic k d r e a p t a p e n t r u m e n i u d e c o n t *
Visible T ru e

5. Tratm evenimentul C lick pentru butonul Ascunde Forma. Executai dublu


click pe el i scriei n corpul ftand/er-ului codul evideniat n B old:

private void buttonl_Click(object sender, EventArgs e)


(
// Ascunde forma aplicaiei
t h i s .H i d e ();
}

6. n designer tray selectai referina notifyiconl i facei dublu click pe


opiunea Ascunde, a meniului contextual. n handler-ui de tratare a
evenimentului C lick, introducei codul:

private void ascundeToolStripMenuItem_Click(


object sender, EventArgs e)
{
// Ascunde forma aplicaiei
t h i s .H i d e ();
202 Partea I l-a . P rogram are W indow s cu V isual C# E xpress Edition f
---------------------------------------------------------------------------------------- g
7. Acionai dublu click pe opiunea Reafiseaza a meniului contextual, pentru
tratarea evenimentului C lick. n corpul metodei de tratare, introducei
codul: ^
'-r
private void reafiseazaToolStripMenuItem_Click( 'g
object sender, EventArgs e) ^
I i
this.Visible = true;
} 4"
.4 * i
4
8. Dorim ca la dublu click pe icon n notify area forma s redevin vizibil f '
Pentru aceasta, tratm evenimentul D o u b le c lic k pentru N o tify lc o n |
Selectai n designer tray referina notifyiconl, apoi n fereastra i
P ro p e rtie s selectai butonul Events (fulgerul). Acionai dublu click pe ^
evenimentul D o u b le c lic k . n corpul metodei de tratare scriei: -4

private void notifyIconl_DoubleClick(object sender,
EventArgs e)
1
this.Visible = true;
1 .

9. Tratm evenimentul C lic k pentru opiunile din meniul contextual. Selectai *


n designer tray referina contextMenuStripl. Acionai dublu click pe
opiunea Ascunde. n editor, scriei codul:

private void ascundeToolStripMenuItem_Click(


object sender, EventArgs e) 'S
{ ' I
this.Hide (); j
}

10. Acionai dublu click pe opiunea Reafiseaza. n editor scriei codul:

private void reafiseazaToolStripMenuItem_Click( t


object sender, EventArgs e)
* i
this.Visible = true;
} J

11. Compilai i rulai cu F5.

La executare, iconul rmne n permanen vizibil n zona de notificare.


C apitolul 7. Controalele W indows F orm s 203

A c u n d e Fofma

La click pe butonul Ascunde Forma, forma devine invizibil. La dublu click pe icon,
forma redevine vizibil, iar iconul rmne vizibil. Din meniul de context putei de
asemenea s controlai vizibilitatea formei:

De reinut:
* Controlul N o tifylco n plaseaz un icon n zona de notificare din system
tray. Iconul reprezint o scurttur pentru procesele care lucreaz n
background.
* Controlul rspunde la evenimente (C lick, D o u b le c lic k ) i admite un
meniu contextual.

F o n tu ri

Fonturile nu sunt controale .NET. Clasa F ont este definit n spaiul de


nume S ystem .D raw ing. Un obiect de tip Font ncapsuleaz un format particular
204 Partea a II-a. Program are W indow s cu V isual C# E xpress Edition

de text, incluznd stilul, dimensiunea. Toate controalele de baz au proprietatea


Font, care v permite s specificai caracteristicile fontului care va fi afiat n
control. Setrile fontului se pot face design time, (din fereastra Properties) sau run
time.

Exemplu:
Setm fontul afiat de ctre o etichet:

Labei e = new L a b e i ();

// Utilizm unul dintre constructorii clasei Font


// pentru a crea un nou font
e.Font = new Font("Arial", 10, FontStyle.Italic);

Stilurile Fonturilor

Enumerarea FontStyle din spaiul de nume System.Drawing are ca membri


enumeratorii: Regular, Bold, Italic, Underline i Strikeout. Acetia determin
stilul aplicat textului.
Cnd lucrai cu un editor de text, lucrurile se complic puin, pentru c mai
multe stiluri din cele de mai sus pot fi aplicate aceleai poriuni selectate de text.
Aplicarea unui nou stil nu trebuie s invalideze stilul anterior. De exemplu:

Aceast p o riu n e de te x t conine stilurile Bold, Italic i Underline".

Aplicaia FontStyleExample
Proiectul introduce stilurile Bold, Italic, Underline, ntr-un control
RichTextBox:

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


FontStyleExample.

2. Din Toolbox alegei un control TooStrip i piasai-l pe suprafaa formei.


Adugai trei butoane n acest control. Selectai pe rnd cele trei butoane
i din fereastra Properties atribuii proprietii Text valorile Bold, Italic,
Underline, iar proprietii DysplayStyle valoarea Text.

3. Aducei pe suprafaa formei un control de tip RichTextBox. Setai din


fereastra Properties, cmpul Dock la valoarea FUI.

4. Tratm evenimentul Click pentru fiecare buton. Dublu click pe butonul


Bold. Handler-ui de eveniment este:

private void toolStripButtonl_Click(object sender,


EventArgs e)
C apitolul 7. C ontroalele W indow s F orm s 205

{
Font vechiulFont, noulFont;

// Returneaz fontul folosit n textul selectet


vechiulFont = t h i s .richTextBoxl.SelectionFont;

// Dac vechiul font era stil Bold, nlturm


// formatarea
if (vechiulFont.Bold)
{
noulFont = new Font(vechiulFont,
vechiulFont.Style & ~ FontStyle.Bold);
}
else
{
noulFont = new Font(vechiulFont,
vechiulFont.Style | FontStyle.Bold);
}
// Inserm noul font si redm focusul
// controlului RichTextBox.
t h i s .richTextBoxl.SelectionFont = noulFont;
th i s .richTextBoxl.F o c u s ();
}

5. Dublu click pe butonul Italic. Handler-ul de eveniment va avea acelai cod


cu cel ataat evenimentului B o ld, cu unica diferen c n toate locurile
cuvntul Bold se nlocuiete cu italic.

6. Dublu click pe butonul U nderline. Handler-u\ de eveniment va avea


acelai cod cu cel ataat evenimentului B o ld , cu unica diferen c n toate
locurile cuvntul Bold se nlocuiete cu Underline".

7. Compilai i rulai cu F5.

! Bold, Ita lic Underline

E prietenul meu acela


care ma w rbesfe de birtg
pe la spate.
Thomas Fuffer

ncotro li-i drumul oare ?


Zbiar Mfc-sla aman.
Se marif-o vrjitoare ?
l ngroappe Satan ?
Aleksandr Pitskin
206 Partea a Il-a . P rogram are W indow s cu V isual C# E xpress Edition

Observaie:
> Codul prezent n metodele handler verific mai nti dac stilul dorit este
deja prezent. Dac este, l nltur.
> Pentru adugarea sau nlturtarea unui stil nou, fr a afecta celelalte
stiluri prezente, se efectueaz operaii pe bii cu enumerarea F ontS tyle.
( O r logic pe b ir (|) adaug un stil nou, iar A n d logic pe bii', aplicat
negrii noului stil, nltur noul stilul dintre cele prezente. Exemple:

// Adaug stilul Underline:


vechiulFont.Style | FontStyle.Underline

// nltur stilul Underline


vechiulFont.Style ~ FontStyle.Underline

Fonturile instalate

Cu ajutorul unui obiect al clasei installedFontCollection, definit n


spaiul de nume S yste m .D ra w in g .T e xt se obin fonturile instalate n sistem, astfel:

using System.Drawing.Text;
InstalledFontCollection fnt = new InstalledFontCollection();

Proprietatea Families a clasei InstalledFontCollection returneaz un


tablou de referine la obiecte de tip FontFamily. Fiecare obiect ncapsuleaz o
familie de fonturi, iar prin proprietatea Name, returneaz numele fontului:

foreach (FontFamily fam in fnt.Families)


System.Console.WriteLine(fam.Name);

Vom vedea un exemplu dup paragraful urmtor.

Desenarea fonturilor

.NET F ra m e w o rk ofer posiblitatea de a desena pe suprafeele formelor sau


ale controalelor. Se pot desena linii, forme geometrice, imagini sau fonturi. n acest
paragraf ne vom ocupa numai de desenarea fonturilor. Pentru desenare, avei
nevoie de un obiect de tip Graphics. Clasa Graphics este definit n spaiul de
nume System.Drawing.
Fonturile se deseneaz cu metoda D r a w S t r i n g O . Una dintre versiuni
este: DrawString(String, Font, Brush, float, float). Deseneaz
textul specificat de obiectele String i Font, cu pensula indicat de obiectul
Brush, la locaia indicat. Ultimii doi parametrii indic coordonatele X i Y ale
colului stnga sus al textului. Dac de exemplu dorim s desenm pe suprafaa
C apitolul 7. Controalele W indows F orm s 207

unei forme, atunci cel mai bun moment pentru desenare este acela al desenrii
formei i vom trata evenimentul P a in t al formei.

Aplicaia FontDrawingExampIe
Proiectul de fa determin fonturile instalate n sistem i populeaz un
combobox cu numele acestora. La selectarea unui font din list, numele fontului se
va deseneaz pe suprafaa formei.

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


FontDrawingExampIe.

2. Din Toolbox, plasai pe suprafaa formei un control de tip C om boB ox.

3. Tratm evenimentul Load generat la ncrcarea formei. Acionai dublu


click pe suprafaa formei. Scriei codul marcat n B old, n handler-ul de
eveniment:

private void Forml_Load(object sender, EventArgs e)


{
// Determin fonturile instalate
InstalledFontCollection fnt =
new InstalledFontCollection();

// Adaug numele fiecrui font n list


foreach (FontFamily fam in fnt.Families)
comboFont.Items.Add(fam.Name);
}

4. n antetul fiierului Forml.cs, adugai directiva:

using System. Dravring. Text;

5. Dorim ca desenarea fontului s se produc odat cu redesenarea formei.


Form redesenarea formei, la fiecare selectare a unui item n C om boB ox.
Tratm evenimentul SelectedlndexC hanged. n acest scop, facei dublu
click pe controlul C om boB ox. Scriei codul:

private void comboBoxl_SelectedIndexChanged


(object sender, EventArgs e)
t
// Invalideaz suprafaa formei, fapt
// care cauzeaz redesenarea acesteia
t h i s .Invalidate();
}

6. Tratm evenimentul P aint pentru form. Selectai forma n Form Designer


i din fereastra P roperties acionai dublu click pe evenimentul Paint.
Scriei codui marcat n Bold, n handler-ul de eveniment:
208 P artea a II-a. Program are W indow s cu V isual C # E xpress E dition

private void Forml_Paint(object sender,


PaintEventArgs e)
{
try
{ // Deseneaz fontul pe suprafaa formei
e .Graphics.DrawString(comboBoxl.T e x t ,
new Font(comboBoxl.Text, 40),
Brushes.B l a c k , 10, 50);
}
catch (ArgumentException ex)
{
MessageBox.S h o w (ex.Message);
1

7. Compilai i lansai n execuie cu F5.

iBUBtreaimai
Jokerman LET
Kartika
LaB am b d LET
Latha
Lucid Console
Lucida S n s Unicode
Mangal______________

TabC ontroI

Un T a b C o n tro I conine pagini suprapuse, numite pagini tab. O pagin tab


este o instan a clasei TabPage. Pagina tab curent se schimb prin cu click cu
mouse-ul pe fab-ui dorit sau se poate face programatic. Paginile tab suport alte
controale, n mod similar formelor. Astfel, un T a b C o n tro I poate constitui o
alternativ unei afiri succesive a mai multor forme.

Principalii membrii ai clasei TabControI

P rop rie t i :
C apitolul 7. C ontroalele W indows F orm s 209

Selectedlndex - Returneaz sau seteaz indexul paginii tab selectate


SelectedTab - Returneaz sau seteaz pagina tab selectat
TabCount - Returneaz numrul de fab-uri din control
TabPages - Returneaz colecia de fab-uri din T a b C o n tro l

Metode:

G e t C o n t r o l () - Returneaz obiectul TabPage de la locaia specificat


G e t lte m s () - Returneaz colecia de obiecte TabPage aparinnd
controlului TabControl.

Evenimente:

Selected - Se declaneaz cnd se selecteaz un Tab


SelectedlndexChanged - Se declaneaz cnd proprietatea
S e le c t e d ln d e x s-a modificat

Aplicaia TabControlExample
Aplicaia pe care o propunem utilizeaz un TabControl pentru afiarea
imaginilor. 7ab-urile controlului se adaug runtime, n momentul n care se ncarc
o imagine de pe disc. Operaiile se execut ia apsarea butoanelor unui control
ToolStrip. Acestea sunt:

> Open - ncarc o imaginede pe disc i o afieaz ntr-un tab nou.


> Next - selectarea fab-ului urmtor
> Prev - selectarea fab-ului anterior
> Glose - nchiderea fab-ului curent
> Close AII - nchiderea tuturor fab-urilor

Urmai paii:
1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele
TabControlExample.

2. Din Toolbox, plasai pe suprafaa formei un control de tip ToolStrip i un


TabControl.

3. Selectai TabControl-ul, apoi n fereastra Properties setai proprietatea


D ock la valoarea F i i i . tergei cele dou tab-uriimplicite din control
(acionai click dreapta pe fiecare tab i selectai) Remove Tab.

4. Adugai cinci butoane pe ToolStrip, desprite printr-un obiect de tip


separator. Forma trebuie s arate astfel:
210 P a r te a a I l- a . P r o g r a m a r e W in d o w s cu V isu a l C # E x p re ss E d itio n

Butoanele din T o o lS trip trebuie s afieze text. Ca s obinei asta,


acionai click dreapta pe fiecare buton, apoi alegei DisplayStyle i
selectai Text. Mai departe, n fereastra P ro p e rtie s, atribuii proprietii
T ext valorile corespunztoare:

Insert y Image
i
ImageAndText
Select

Cut

5. Declarm un cmp privat n clasa Forml, care stabilete caracterul


separator pentru cile de director. n S o lu tio n E xp lo re r, click dreapta pe
F o rm l, selectai View Code, apoi n fiierul F o rm l.cs, n clasa Forml,
scriei:

private char[] sep = new charf] { '\\' };

6. Din T o o lb o x , tragei pe suprafaa formei un control de tip O penF ileD ialog.


C apitolul 7. C ontroalele W indows F orm s 211

7. Tratm evenimentul C lick pentru butonul A dd Image. Acionai dublu click


pe buton. n handler-ul de eveniment, scriei codul evideniat n Bold:

private void toolStripButtonl_Click(object sender,


EventArgs e)
1
string[] a u x ;
string fullPath; II Calea pn la fiierul imagine
string imgName; // Numele fiierului imagine

// Setm un filtru pentru fiiere de tip imagine


openFileDialogl.Filter = "Fiiere suportate " +
" (*jp g ;*p n g ;*.i c o ;*.g i f ;*.b m p ;*.tiff)" +
" I*-jpg;*.png;*.ico;*.gif;*.bmp;*.tiff " +
" |A11 files <*.*)

// Dac dialogul se nchide prin apsarea OK


if (openFileDialogl.ShowDialog() ==
DialogResult.OK)
{
// Obinem calea pn la fiier
fullPath = openFileDialogl.FileName;

// Separm calea n stringuri separate prin '\ *


aux = fullPath.Split(sep);

// Numele imaginii e ultimul string


imgNarae = aux [a u x .Length - 1] ;

// Crem un tab nou i un PictureBox


TabPage tP = new TabPage(imgName);
PictureBox pB = new PictureBox();

// ncrcm n p i c t n r e b o x imaginea
pB.Image = Image.FromFile(fullPath);

II Stabilim poziia i dimensiunea imaginii pe


// tab. (x i y fa de colul stnga sus a
II tab-ului, limea i nlimea)

p B .SetBounds(
(tabControll.Width/2) - p B .I m age.Width / 2),
(tabControll.Height/2)- (pB.Image.Height/2),
p B .Image.W i d t h , p B .I m age.Height);

II Adugm pb pe tab
tP.Controls.Add(pB);

// Adugm tab-ul pe TabControl


tabControll.TabPages.Add(tP) ;
212 P artea a H -a. Program are W indow s cu V isu al C # E xpress E dition

// Tab-ul adugat devine cel selectat


tabControll.Selectedlndex =
tabControll.TabPages.Count - 1;
>
}

8. Tratm evenimentul C lick pentru butonul Next. Facei dublu click pe


buton. n metoda de tratare, scriei:

private void toolStripButton2_Click(object sender,


EventArgs e)
{
// Dac exist tab-ul urmtor
if (tabControll.Selectedlndex + 1 <
tabControll.TabPages.Count)
{
// l selectm
tabControll.Selectedlndex =
tabControll.Selectedlndex + 1;
}
}

9. Tratm evenimentul C lick pentru butonul Prev. Facei dublu click pe


buton. n metoda de tratare, scriei:

private void toolStripButton3_Click(object sender,


EventArgs e)
{
// Dac exist tab-ul precedent
if (tabControll.Selectedlndex - 1 >= 0)
{
// l selectm
tabControll.Selectedlndex =
tabControll.Selectedlndex - 1;
}
}

10. Tratrn evenimentul C lick pentru butonul Close. Facei dublu click pe
buton. n metoda de tratare, scriei codul evideniat n B old:
private void toolStripButton4_Click (object sender,
EventArgs e)
{
// Dac mai exist pagini (tab-uri)
if (tabControll.TabPages.Count > 0)
{
/ / O tergem pe cea selectat
tabControll.TabPages.RemoveAt(
tabControll.Selectedlndex);
}
C apitolul 7. Controalele W indows F orm s 213

11. Tratrn evenimentul C lick pentru butonul C/ose Ml. Facei dublu click pe
buton. n metoda de tratare, scriei codul evideniat n B old:

private void toolStripButton5_Click(object sender,


EventArgs e)
{
// Ct timp mai sunt pagini (tab-uri)
while (tabControll.TabPages.Count > 0)
{
// tergem pagina selectat
tabControll.TabPages.RemoveAt(
tabControll.Selectedlndex);
}
}

12. Compilai i rulai cu F5.

La rulare, cu Add Image se pot ncrca mai multe imagini n pagini diferite, cu
butoanele Next i Prev se parcurg tag-urile deschise, cu Close se nchide tab-
ul selectat, iar cu Close AII se nchid toate paginile.

Probleme propuse
1. Realizai o aplicaie care utilizeaz un T a b C o n tro l care preia comenzile
clienilor la o pizzerie. Paginile controlului trebuie s conin controale de
tip T extB ox, C om boB ox, C heckBox, R a d io B u tto n i B utto n . La finalul
comenzii, aplicaia afieaz ntr-un dialog ntreaga comanda, mpreun cu
preul final.

2. Realizai un proiect care un utilizeaz un T a b C o n tro l cu apte pagini.


Controlul reprezint jurnalul unui elev i fiecare pagin corespunde unei
zile a sptmnii. Controlul trebuie s conin cel puin csue de editare.
Dup completarea zilei a aptea, se apas un buton care creeaz un nou
tab. n acest tab se vor afia ntr-un T e xtB o x informaiile introduse n
timpul sptmnii (n rezumat sau integral - dumneavoastr decidei).

Controalele ListBox, ComboBox i CheckedListBox

Toate cele trei controale motenesc clasa L is tC o n tro l i servesc la afiarea


unei liste de itemuri. Itemurile apar n list ca iruri de caractere i pot fi selectate
prin click cu mouse-ul.
Controlul L is tB o x poate oferi selecie simpl sau multipl, n funcie de
valoarea proprietii S e le c tio n M o d e .
Controlul C om boB ox combin un T extB ox cu un L istB o x, permind
utilizatorului s selecteze itemi dintr-o list, sau s introduc noi itemi.
Controlul C he cke dL istB o x afieaz o list de itemi care pot selectai cu
ajutorul unui checkbox prezent pentru fiecare item.
214 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress Edition

Reinei c n aceste tipuri de liste se pot nsera obiecte, dar c ceea ce se


vede este reprezentarea ca ir de caractere a acestor obiecte.

Adugarea item ilorn liste


Itemii se pot aduga design time sau run time.

Adugarea itemilor design time


O variant simpl este s selectai controlul, facei click pe sgeata din colul
stnga sus, alegei Edit Items i introducei itemii manual, cte unul pe linie:

: liitBoxl
l~~l Use date bound ten
Enter the strings in the collection (one per line):
Unbound M ode
' Corine
Edit Items 1 Aiinuta
: Viorel
, Maricel
Ghtocd

| OK |1 Cancftl |

Adugarea item ilor run time


Se folosesc metodele i n s e r t O , A d d () sau A d d R a n g e ). Cu I n s e r t )
inserai un item la o poziie specificat. De exemplu:

// nsereaz n list la poziia 3 un item cu textul "Item 3"


lis t B o x . I t e m s . I n s e r t ( 3 , " Ite m 3 ") ;

Metoda A d d () adaug la sfritul listei un obiect.


Exemplu:

com boB ox. I t e m s . A d d { " Ite m N o u " ) ;

Pentru adugarea eficient a unui numr mare de itemi n list, controalele


furnizeaz metodele B e g in U p d a te () i E n d U p d a te ). Prin utilizarea acestora,
controlul nu este redesenat de fiecare dat cnd un item este introdus n list.
Exem plu:

com boB ox. B e g in U p d a te ( ) ; / / Controlul nu se mai redeseneaz


f o r ( i n t i = 0 ; i < 2 0 0 ; i+ + )
com b o B o x. I t e m s . A d d ( " I t e m u i " + i ) ;
com boB ox. E n d U p d a te ( ) ;
C apitolul 7. C ontroalele W indows F orm s 215

Adaugarea unui interval de itemuri n liste se face cu metoda AddRange).


Aceasta primete un tablou de obiecte, apoi afieaz n list valoarea de tip
string implicit pentru fiecare obiect.
E xem plu:

listBox.Items.AddRange(new object] { "UNU", "DOI", "TREI});

Listele pot prelua itemi. Sursele de date pot fi tablouri, colecii, DataSet-uri.
E xem plu:
stringf] copii = { "Ionel", "Viorel , "Alinei", "Dorel" };
checkedListBox.DataSource = copii;

Itemurile se terg cu metoda RemoveQ. Exemplu:

// terge obiectul caracterizat de irul "Alin"


listBox.Items.Re m o v e ("Alin");

// terge primul item


lisBox.Items.RemoveAt(0) ;

Clasele specifice acestor liste au desigur i alte metode i proprieti utile. Vom
face un mic proiect, pentru introducere n lucrul cu controalele de tip list.

Aplicaia TestListControl

Aplicaia pe care o propunem ilustreaz diferite modaliti de populare


runtime a controalelor ListB ox, C om boB ox i C heckedListB ox:

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


TestListControl.

2. Din T o o lb o x plasai pe form cu ajutorul mouse-ului un control L istB o x,


un control C om boB ox i un control C h e cke dL istB o x. Adugai de
asemenea trei Label-uri pe care le vei eticheta corespunztor controalelor
de tip list.

3. Sub primele dou controale de tip list plasai cte un buton. Sub controlul
de tip checkListBox plasai dou butoane. Stabilii valorile proprietilor
Name ale butoanelor astfel: listButton, comboButton,
checkListButtonl i checkListButton2, iar valorile proprietilor
Text, aa cum se vede n figur:
216 Partea a Il-a . Program are W indow s cu V isual C # Express E dition

ListBox ComboBox CheckedListBox

[ Incarca LislBox Incarca ComboBox Incarca o lista

Incarca alta lista

4. Dorim ca la ncrcarea formei s ncrcm i controlul C h e c k L is tB o x cu o


prim list de itemi. Pentru aceasta, tratm evenimentul Load care se
declaneaz la ncrcarea formei. Facei dublu click pe suprafaa formei.
Completai astfel corpul handler-ului de eveniment:

private void Forml_Load(object sender, EventArgs e)


{
// Un tablou de referine la obiecte de tip string
string[] copii = { "Ionel", "Viorel", "Alinei",
"Dorel" };
// Sursa de date este tabloul
checkedListBoxl.DataSource = copii;
}

5. Definim clasa, Elev, n fiierul Forml.cs. Avei grij, Visual C# Express


2008 cere ca definiia oricrei clase s urmeze definiiei formei:

class Elev
{
private string nume;
public Elev(string n) { nume = n; }
public string Nume
{
get { return nume; }
}
>

Vom defini de asemenea un cmp privat el n clasa Forml, de tip referin


la un tablou de obiecte de tip Elev:

private Elev[] el;

6. Tratm evenimentul C lick pentru butonul lis tB u tto n . Acionai dublu click
pe acesta. Introducei acest cod n metoda de tratare:
C apitolul 7. C ontroalele W indows F orm s 217

private void listButton_Click(object sender,


EventArgs e)
{
// Membrul clasei Elev care va fi afiat n list
// ca ultim item
listBoxl.DisplayMember = "Nume";

// Tabloul de referine de tip object poate reine


// referinele ORICROR TIPURI de obiecte
listBoxl.Items.AddRangenew object[]{ "UNU", "DOI",
"TREI", new E l e v ("Nelutu") });
}

7. Tratm evenimentul C lick pentru butonul c o m b o B u tto p . Acionai dublu


click pe acesta. Completai astfel metoda de tratare:

private void comboButton_Click(object sender,


EventArgs e)
{

/* ncepnd de la apelul BeginUpdate() i pn la


EndUpdate) controlul nu se mai redeseneaz, ceea
ce sporete viteza de adugare n list */
comboBoxl.BeginUpdate();'
for (int i = 0; i < 20; i++)
comboBoxl.Items.Add("Itemul " + i) ;
comboBoxl.EndUpdate{);
}

8. Tratm evenimentul C lick pentru butonul checkListButtonl. Acionai


dublu click pe acesta. Completai astfel metoda de tratare:

private void checkListButtonl_Click(object sender,


EventArgs e)
{
string[] copii = { "Ionel", "Viorel", "Alinei",
"Dorel" };
checJcedlistBoxl.DataSource = copii;

9. Tratm evenimentul C lick pentru butonul checkListButton2. Acionai


dublu click pe acesta. Completai n acest mod metoda de tratare:

private void ciieckListButton2_Click(object sender,


EventArgs e)
{
// Crem obiectele care se insereaz n list
el = new Elev[] { new Elev("marius"),
new Elev("lenuta")};
218 P artea a Il-a . P rogram are W indow s cu V isu al C# Express E dition

// Sursa de date este el


checkedListBoxl.DataSource = el;

// Membrul clasei Elev care se va afia


// n list este proprietatea Nume
checkedListBoxl.DisplayMember = "Nume";
1

10. Compilai i rulai cu F5.

1 8 F o rm l " ' 1 i ' i M i \


r - V I V E iL '

| ListBox ComboBox CheckedListB ox |

1UNU 1
i DOI j [ j ] Viorel
Itemul 0 Ai
: TREI
1temui 1 i O A,inel
! Nelutu !
Itemul 2 j| | Dorel
? |
Itemul 3 ~
- - Itemul 4 'J.'f - fHnuM
Itemul 5
| Incarca ListBox | ! ( Incarca o lista ]
Itemul 6
i Itemul 7 V.
| Incarca alta lista ]

Cele trei controale se ncarc runtime, prin acionarea butoanelor corespunztoare.

C ontroalele TrackB ar, N u m ericU pD ow n i


D o m ain U p D o w n

Aceste controale se numesc i controale de domeniu, deoarece utilizatorul


poate introduce un numr limitat de valori dintr-un domeniu prestabilit. Introducerea
datelor se face n mod vizual, acionnd de regul cu mouse-ul.

TrackBar

TrackBar.

0 ------------

Este un control scro//-abil, cu ajutorul crui utilizatorul poate alege o valoare a


proprietii Value, cuprins ntre o valoare maxim i minim. Limitele extreme se
impun prin atribuirea de valori proprietilor Minimum i Maximum. Implicit, aceste
valori sunt 0 i 10.
C apitolul 7. C ontroalele W indows F orm s 219

NumericUpDown

NumericUpDown: ill

Este un control care conine o singur valoare numeric, pe care utilizatorul o


poate modifica acionnd click pe butoanele Up sau Down ale controlului.
Utilizatorul poate s i introduc valori, dac proprietatea ReadOnly este setat
true.

D om ainU pD ow n

D o m a in U p D o w n : j P r S 'i t e m p i

Este similar cu un L istB o x n aceea c ofer o list de opiuni ntre care utilizatorul
poate alege. Diferena fa de L is tB o x este c un singur item este vizibil la un
moment dat, iar utilizatorul poate naviga n list doar acionnd sgeile Up i
Down ale controlului. Pentru crearea coleciilor de obiecte care vor alctui lista, se
utilizeaz metodele Add(), la fel ca pentru celelalte controale de tip list.

Transparena i opacitatea controalelor

Opacity i Transparency sunt dou proprieti ale formelor. Au rolul de a


regla gradul de trasparen a formei, dar i a controalelor care se gsesc pe
suprafaa formei. Cnd proprietatea Opacity este setat la valoarea 1,00 (100%),
atunci forma este perfect vizibil. Dac valoarea este 0, atunci forma, inclusiv
bordurile, marginile i controalele de pe form sunt invizibile. Valori intermediare,
regleaz niveluri proproionale de tranparen.
n ce privete proprietatea Transparency, acesteia i este ataat o
culoare. ntreaga arie a formei care are aceeai culoare (proprietatea BackColor)
devine trasparent, iar orice aciune cu mouse-ul pe suprafaa devenit
transparent, este transferat ferestrei de sub aria devenit trasparent. Aceast
caracteristic v permite s definii controale cu forme neregulate.

Aplicaia Opacity
Vom utiliza controalele TrackBar, NumericUpDown i D om ainU pD ow n
pentru a regla opacitatea unei forme. Evident, unul singur dintre cele trei controale
ar fi fost suficient, ns scopul nostru este de a nva s le utilizm pe toate.
1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele
Opacity.

2. Din T o o lb o x plasai pe form cu ajutorul mouse-ului un control


N um ericU pD ow n, un control D om ainU pD ow n i un control TrackB ar.
Adugai de asemenea trei Label-uri pe care le vei eticheta corespunztor
controalelor i un buton cruia setai-i proprietatea Text: la Revenire:
220 Partea a Il-a . Program are W indow s cu V isu al C # Express Edition

I Revenire J

NumeiicUpDown: 10

DomainUpDown: !0 paritate 100*

TfackBar:

3. Selectai controlul D om ainU pD ow n. Din fereastra P roperties, atribuii


proprietii T e xt valoarea Opacitate 100%". Selectai proprietatea Item s,
apoi apsai butonul din dreapta. n dialogul String Collection Editor,
introducei 10 itemi, cte unul pe linie, cu textul: Opacitate 100%",
Opacitate 90%, ... Opacitate 0%.

4. Tratm evenimentul S cro ll pentru TrackBar. Dublu click pe control. Scriei


codul marcat n B old, n handler-ul de eveniment:

private void trackBarl_Scroll(object sender,


EventArgs e)
(
/ / Odat cu creterea valorii Value de la 0
// 10, opacitatea formei trebuie s scad
this.Opacity = 1 - (double)trackBarl.Value / 10;
}
5. Tratm evenimentul S electedlndexC hanged pentru controlul
D om ainU pD ow n, n scopul de a modifica opacitatea n raport cu indexul
itemului. Dublu click pe control. Scriei codul:

private void domain_SelectedItemChanged(object sender,


EventArgs e)
{
// Opacitatea formei scade cu creterea
// indexului itemului selectet
this.Opacity = 1
(double)domainUpDownl.Selectedlndex / 10;
}

6. Tratatm evenimentul ValueC hanged pentru controlul N um ericU pD ow n,


pentru a modifica opacitatea n funcie de valoarea afiat n control.
Acionai dublu click pe control. Scriei codul:
C apitolul 7. C ontroalele W indows Form s 221

private void numericUpDownl_ValueChanged(object sender,


EventArgs e)
{
// Value este valoarea afiat n control
this.Opacity = 1 - (double)numericUpDownl.Value/10;
}

7. Pentru reiniializarea valorilor controalelor, dar i pentru readucerea formei


la opacitate maxim, tratm evenimentul C lic k pentru butonul Revenire".
Dublu click pe buton. Scriei codul marcat n B o ld , n handler-ul de
eveniment:

private void buttonl_Click(object sender, EventArgs e)


(
this.Opacity = 1 ; // Forma devine opac

// Reiniializarea valorilor n controale


trackBarl.Value = 0;
numericUpDovml.Value = 0;
domain.Text = "Opacitate 100%";
}

8. Compilai aplicaia i rulai cu F5.


* " "

iti cafipion : 3
k_j im age Test
a iDion 2 C4
O Im agineAudioEuIulia
Q Dion 2Q C 5
Revenire
a ipion 2 0 0 6
O JAVA 1.3
ffl Q '1PIN 200?
O pic-o 2 0 0 8
- t ^ -j AV A Tutorial SUN
i NumeiicUpDowi:
avadc-c
ffi D G
JavaE'/erriple ->2
o C<
DomainUpOown: Opacilate SQZ
00 cp
; javaxml
C!
yjjbuildet'
S Q
:domainUpDov*T];,
--tr-a TiackBdi:
ffl _ ' ' ' Zj'jD BC '
e? jie.
Bl i e .
V Ojdb'
a P3SP
gard X jw t ........

Opacitatea formei se poate seta n mod independent cu ajutotorul celor trei


controale.

Aplicaia Transparency
Atunci cnd dorii ca anumite poriuni ale formei s fie transparente i
aciunea mouse-ului pe suprafaa transparent s se transfere ferestrelor de sub
form, utilizai proprietatea T ra n sp a re n cy a formelor.
222 P artea a Il-a . Program are W indow s cu V isual C # E xpress E dition

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


Opacity.

2. Din Toolbox plasai pe form cu ajutorul mouse-ului un control de tip


Panel i dou butoane.

3. Selectai panoul i n fereastra Properties atribuii proprietii BackColor


valoarea Gray. Setai pentru cele dou butoane proprietatea Text la
valorile: Panou Transparent, respectiv Forma transparenta".

4. Tratm evenimentul Click generat de butonul cu eticheta Panou


T ransparent. Facei dublu click pe buton. Scriei n metoda de tratare
urmtorul cod :

private void buttonl_Click(object sender, EventArgs e)


{
// Toate zonele formei de culoare gri,
// devin transparente (suprafaa panoului)
t h i s .TransparencyKey = System.Drawing.Color.Gray;
}

5. Tratm evenimentul Click generat de butonul cu eticheta Forma


Transparenta". Dublu click pe buton, iar n metoda de tratare scriei:

private void button2_Click(object sender, EventArgs e)


(
// Zonele de culoarea implicit a controalelor
// devin transparente (exteriorul controlului Panel)
t h i s .TransparencyKey =
Sys t e m .Drawing.Sys temColors.Control;
)

6. Compilai i executai cu F5.

Panoul e transparent Forma e transparent


C apitolul 7. C ontroalele W indows F orm s 223

Observai c numai suprafaa formei devine transparent, nu i marginile,


bara de titlu, sau celelalte controale de pe form.

Controlul ProgressBar
Controlul nu permite nici o aciune a utilizatorului. Este destinat s indice n
mod vizual progresul unei aplicaii care decurge lent, aa cum sunt printarea unor
documente, copierea unui numr mare de fiiere, scanarea unui disc.
Stilul de afiare al controlului este determinat de proprietatea s t y l e . Exist
trei stiluri:
O bar continu care se umple de la stnga la dreapta
Blocuri segmentate care progreseaz de la stnga la dreapta.
Blocuri care oscileaz.

Proprietatea V alue este valoarea care reprezint progresul curent al


aplicaiei. Poziia curent a barei de progres este n legtur direct cu Value.
Proprietile Minimum i Maximum sunt limitele de valori pentru Value. Minimum
este de regul setat la 0, iar Maximum este setat la o valoare care indic
terminarea operaiei.
ntreaga operaie pentru care vizualizai progresul este format dintr-un
numr de operaii pe care le considerai elementare. Dup fiecare operaie
elementar, cu ajutorul metodei PerformStepO incrementai valoarea barei de
progres cu valoarea s te p .

E xem plu de utilizare:

ProgressBar p = new ProgressBar();


// Maximum poate fi de exemplu numrul de fiiere
// care trebuie copiate
p.Maximum = 500;
p.Mimnimum = 500;
p .Value = 0;
p.Step = 5;

for (int j. = p.Minimum; i < p.Maximum; i += p.Step)


{
// Operaie elementar (de exemplu, copierea unui fiier)
// Incrementeaz bara de progres
progress.PerformStep();
)

Aplicaia pe care o vom prezenta n cadrul temei C o n tro lu l Tim er ilustreaz i


utilizarea unui progress bar.
224 Partea a II-a. Program are W indow s cu V isual C# E xpress E dition

C ontrolul Tim er

Contrulul funcioneaz ca i cronometru. Declaneaz un eveniment la un


interval de timp specificat de ctre programator. .NET implementeaz cteva
cronometre dintre care discutm dou:

1. Primul, este definit de clasa S ystem s.W indow s.F orm s.T im er. Se
utilizeaz n aplicaii de tip Windows Forms. El apare n mod implicit n
T o o lb o x i trebuie afiat ntr-o fereastr. Se utilizeaz numai n medii cu
un singur thread. Acurateea este de aproximativ 55 milisecunde.
2. Al doilea, definit de clasa S ystem .T im ers.T im er, este mai performant.
Poate fi folosit n medii muitithread. Nu se gsete n mod implicit n
T o o lb o x, ns poate fi adus acolo, aa cum vom vedea.

Exist asemnri i deosebiri ntre cele dou timer-e. Ambele declaneaz


un eveniment la un interval specificat. Primul declaneaz evenimentul T ick, iar al
doilea, evenimentul Elapsed. Ambele au metodele S t a r t () i S to p O , i
proprietatea Enabled.

Aplicaia Timer.ExampIe

Aplicaia execut sarcinile:


Utilizez timer-u\ S ystem .W indow s.T im er care declaneaz un
eveniment T ic k la interval de dou secunde, timp de 20 de secunde.
Numrul de secunde se afieaz ntr-un control Labei, iar progresul se
vizualizeaz cu o bar de progres. Cronometrul poate fi pornit i oprit cu
butoanele Stop i Start.
Utilizeaz timer-u\ S ystem .T im ers.T im er pentru afiarea orei, ntr-un
control Labei. Evenimentul Elapsed se declaneaz la interval de o
secund.

1. Creai un proiect de tip W indow s F orm s A p p lic a tio n , cu numele


TimerExample.
2. Aducei din T o o lb o x pe suprafaa formei un control de tip Tim er, dou
controale de tip Button, un P ro g re ssB a r i i ase controale Labei:

lbell

!abel2 iabe!3 buttonl

[ buUon 2

lbeI4 1abe!S

!abel5
C apitolul 7. C ontroalele W indows F orm s 225

3. Vom seta mai nti etichetele butoanelor:


a. Selectai labell. n fereastra Properties, setai fontui la
dimensiunile (16, 50). Atribuii proprietii Text valoarea
S ystem .W indow s.F orm s.T im erSelectai label2. Setai fontul la
dimensiunile (16, 50). tergei numele etichetei. Selectai label3.
Atribuii proprietii Text valoarea Incrementare la 2 secunde.
b. Selectai label4. Setai fontul la dimensiunile (16, 50). Atribuii
proprietii Text valoarea "System. Timers. Timer. Selectai
labelS. Setai fontul la dimensiunile (16, 50). tergei numele
etichetei. Selectai label6. Atribuii proprietii Text valoarea
Afieaz ora exact.
c. Selectai buttonl. Atribuii proprietii Text valoarea S tart.
Selectai button2. Atribuii proprietii Text valoarea Stop.

iii
System.Windows.Forms.Timer
label2 Incrementare la 2 tecunde Slarl j
1 1 1 Stop j

System.Timers .Timer Afineaz ora exact

Iabel5

4. Selectai referina timerl n designer tray. n panoul P roperties, setai


proprietatea Name la valoarea winTimer. Setai la 1000 (o secund)
valoarea proprietii Interval. Este intervalul la care se declaneaz
evenimentul T ick.

5. Vom aduga un timer-ul din spaiul de nume


v & M .W fn d o w j
S ystem .T im ers. n T oolbar, n partea cea re,CnmonContn>to-'.
mai de jos, unde nu mai sunt controale, facei
s M tn w .f c locton.:.A..ar**.
click drept i alegei Choose Items... i& Pattk - .' .i w .

.ifee rintln *. M jj
6. n dialogul Choose Toolbox Items, alegei din .r&Me'rm**.aWfctA' I
tab-ul .N E T Framework Components, clasa 1i1Getxrel ~
ij
T im e r din spaiul de nume S ystem .Tim ers. There ere no u m Mb controls h th*s p o u t . Dreg 1j
n item onto tft* text to add * to t i * toobox. j'
Un icon tip ceas apare n partea de jos n
T oolbar. :Q
; show a i

;<!.ChocK* *...
7. Tragei noul T im e r pe suprafaa formei. n
designer tray, selectai referina timerl. n
panoul P rope rtie s, schimbai numele referinei la systemTimer, setai
226 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress E dition

valoarea proprietii Enabled la true, iar a proprietii Interval la


1000. Aceasta nseamn c evenimentul E lapsed se declaneaz la
interval de o secund.

8. Selectai bara de progres. n panoul P roperties, setai proprietatea s te p


la valoarea 2 i proprietatea Maximum la valoarea 20.

9. n fiierul Form1.cs, n clasa F o rm l, declarai un cmp privat, numit tim e ,


care contorizeaz numrul de secunde scurse. n S o lu tio n E xplorer,
facei click drept pe Form1.cs i selectai View Code. Scriei:

private int time = 0;

10. Tratm evenimentul T ic k pentru winTimer. Selectai referina winTimer


n designer tray, apoi n P roperties, acionai dublu click pe evenimentul
T ick. Scriei codul:

private void winTimer_Tick(object sender, EventArgs e)


{
time + = 2 ; //(Jn eveniment Tick la 2 secunde

// Afim timpul n etichet


label2.Text = string.Format("{0}", time);

// Incrementarea barei de progres


progressBarl.PerformStep();
if (time == 20) // Dac s-au scurs 20 secunde
{
// oprim timer-ul i bara de progres
w inTimer.Stop () ;
progressBarl.Enabled = false; // oprim
}
}

11. Tratm evenimentul C lick pentru butonul Start. Facei dublu click pe buton.
Introducei codul:

private void buttonl_Click(object sender, EventArgs e)


{
winTimer.Enabled = true; // Activm timer-ul
if (time 20) // Dac au trecut 20 sec
{ // se fac reiniializri
time = 0;
progressBarl.Value = 0;
)
}

12. Tratm evenimentul C lick pentru butonul Stop. Facei dublu click pe buton.
Introducei codul:
C apitolul 7. C ontroalele W indows F orm s 227

private void button2_Click(object sender, EventArgs e)


(
winTimer.S t o p (); // Oprim cronometrul
progressBarl.Enabled = false; // Oprim progress bar
if (nrTick = 20)
{
nrTick = 0;
progressBarl.Value = 0;
>
1

13. Tratm evenimentul Elapsed pentru systemTimer. Selectai referina


systemTimer n designer tray, apoi n Properties, acionai dublu click pe
evenimentul Elapsed. Scriei codul:

private void systemTimer_Elapsed(object sender,


System.T imers.ElapsedEventArgs e)
{
// Proprietatea Now a clasei DateTime, returnez
// ora exact
label5.Text =System.DateTime.Now.ToLongTimeString();

14. Compilai i rulai aplicaia cu F5.

Captur de ecran la execuie:

I i i
System. W indows. Forms.Timer
12 Incrementare la 2 secunde Start

Stop

System .Timers .Timer ota exacta

14:00:31

C ontroalele P ictu reB o x i Im ag elist

Imagini de fundal pentru controale


Multe controale suport afiarea de imagini, deoarece motenesc
proprietatea Backgroundimage de la clasa Control. ntre aceste controale,
228 Partea a Il-a . Program are W indow s cu V isual C # E xpress E dition

menionm B u tto n , C heckBox, R adioB utton, P ictureB ox. i controalele de tip


container cum sunt Panel, G ro u p B o x i Form suport imagini de fundal.

aDei i :
r D o ............ o.............o
G roupB ox . - , ,
P. ' V t

Anumite controale suport i imagini de prim plan. De exemplu, B u tto n are


n acest scop proprietatea Im age, motenit de la clasa B u tto n B a se . n cazul n
care utilizai att o imagine de fundal ct i de prim plan, imaginea de prim plan se
afiez deasupra.
Controalele au n plus proprieti cu ajutorul crora se pot modifica
caracteristicile imaginilor afiate.
Pentru afiarea design time a unei imagini, se selectaz controlul, se apas
butonul cu etichta din linia proprietii BackgroundlmageLayout sau a
proprietii image. n dialogul Select Resource, bifai Local resource", apoi
apsai butonul Im port.

j OK ~| I Canei I
C apitolul 7. Controalele W indows F orm s 229

Caracteristicilor imaginilor se modific simplu din panoul P ro pe rtie s atribuind valori


urmtoarelor proprieti:

> BackgroundlmageLayout
Are valorile posibile: None, Tile, Center, Strech i Zoom. De exemplu,
mai sus, pentru CheckBox, i RadioButton am ales C e n te r, iar pentru
G rupB o x valoarea Tile.
> ImageAllign
Label-urile nu suport Backgroundlmage deci utilizai Image pentru
afiare, iar pentru modul de afiare, alegei dintre valorile disponibile n
panoul Properties, pentru proprietatea ImageAllign.
> AutoSize
Pentru /abe/-uri, checkbox-un i radiobutoane trebuie s setai aceast
proprietate la valoarea false, altminteri nu vei reui s redimensionai
suprafeele controalelor, astfel nct s potriveasc imaginile.
> TextAllign
Aceast proprietate v permite s stabilii poziia i alinierea textului n
raport cu suprafaa controlului.

Clasa Image
.NET definete clasa im age n spaiul de nume S yste m .D ra w in g , pentru
lucrul cu imagini.
Clasa este abstract, deci nu se pot crea obiecte de acest tip. n schimb, imaginile
se citesc din fiiere cu metoda static FromFile ( ) :

Exem plu:

Image im = Image.FromFile(
Path.Combine(Application.StartupPath, "foto.gif"));
Labei lbl = new lbl L a b e i (); // Creeaz o etichet
lbl.Image = im; // Afieaz imaginea n control

Codul de mai sus ncarc imaginea din fiierul " f o t o . g i f " aflat n foiderul n care
se gsete fiierul assembly (exe) al aplicaiei. Metoda nu recunoate dect
formatele .GIF i .BMP. Eticheta l b l afieaz imaginea ncrcat.
Clasa are proprieti i metode pentru manipularea imaginilor. Metoda
FromStream() ncarc imagini de diferite tipuri nu numai n formatele standard
.GIF sau .BMP. Creaz un stream din care putei descrca imaginea. Sfream-ul
poate s fie de conectat la orice dispozitiv de intrare, de exemplu la o adres de
Internet:

string s = h t t p ://...... /foto.jpg; .1 1 URL


// Sunt necesare obiectele wrq i wrs pentru crearea
// stream-ului
WebRequest wrq = WebRequest.Create(s);
WebResponse wrs = w r q .GetResponse();
Stream str = w r s .G e t R e s p o n s e S t r e a m Q ; // Creaz stream-ul
230 Partea a II-a. P rogram are W indow s cu V isual C # E xpress Edition

Labei lbl = new L a b e i ();

// Afieaz imaginea intr-un control de tip Labei


l b l .Image = I m a g e .FromStream(str);
str.close();

Vom reveni asupra tipului Image.

Controlul PictureBox

P ic tu re B o x este un control aflat la ndemn n T o o lb o x. E folosit pentru


afiarea imaginilor grafice, obinute din fiiere JPEG, GIF, BMP, PNG, iconuri sau
metafiiere.

Prezentm civa membri reprezentativi ai clasei PictureBox.

P roprieti
Image Se seteaz pentru afiarea design time sau run time a
imaginilor
SizeMode Specific modul de afiare a imaginii. Are valorile:
Strechlmage, Centerlmage, Normal,Zoom.
ClientSize Permite modificarea dimensiunii imaginii n timpul rulrii.
ImageLocation Reprezint calea sau URL-ul spre imaginea care se afieaz
n P ictureB ox.

Metode
L o a d () Afieaz imaginea specificat de proprietatea
ImageLocation. Are dou versiuni.
SetBounds() Seteaz limitele controlului, la o anumit locaie, i la
dimensiunile specificate.

Evenim ente
Click Se declaneaz la click pe control
Paint Se declaneaz cnd controlul trebuie redesenat
ClientSizeChanged Se declaneaz cnd proprietatea C lientS ize se modific

Resursele unui proiect Visual C#

Ai vzut c un program C# poate accesa fiiere externe de tip imagine,


problema apare cnd asemenea resurse sunt terse sau mutate din greeal. n
aceste condiii aplicaia nu le mai poate utiliza.
n Visual C# exist posiblitatea s incorporai resurse de care aplicaia are
nevoie: imagini, iconuri, sunete, stringuri n acelai fiier assembly(.exe) care
conine codul compilat ai aplicaiei. Pentru a vedea cum se realizeaz acest lucru,
realizm un mic proiect.
C apitolul 7. C ontroalele W indows F orm s 231

Aplicaia ImageResourceExample

Proiectul va fi unul simplu: pe o form, avem un control P ictureB ox.


Imaginea pe care o afim n control, va fi una luat din resursele proiectului.
Pentru divertisment, implementm i facilitatea de mrire i de micorare a imaginii
(Zoom).

15. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


ImageResourceExample.

16. Aducei din T o o lb o x pe suprafaa formei un control de tip P ictureB ox i


dou butoane.

17. Selectai controlul P ictureB ox. n panoul P roperties, setai pentru


proprietatea S izeM ode valoarea Zoom. Aceasta permite controlului s se
redimensioneze odat cu imaginea.

18. Selectai pe rnd cele dou butoane i stabilii pentru proprietatea Text,
valorile Zoomin, respectiv Zoom O ut

Form1

Zoom in | | Zoom Oul

19. Acum adugm o imagine ca resurs a proiectului. n S o lu tio n E xplorer,


dublu click pe P roperties. Se deschide fereastra E d ito ru lu i de Resurse.
Pe coloana din stnga ferestrei, selectai Resources. Din lista primului drop
down button din stnga sus, selectai Images:
"w .;

Application I j.j^j Images *] Add Resource. .


.-i
.is! Strings +1

Images Q r i+ 2
Build Events
im Icons Ctrl+3

Debug Audio Ctrl+4

Files Ctrl+5 [
Resources
J Other CM +6

Settings
232 Partea a II-a. Program are W indow s cu V isual C # Express E dition

20. Din lista butonului A d d Ressource, selectai Add Existing File

Application Im a g e s 7 J A d d R e so u rc e
1 A d d Existing F ile , .. - , .:
Build .------------------ -1 ....-.............. ..
A d d N e w String
: Build E v e n ts
N e w Im age

: Debug A d d N e w Text File

R e so u rc e s*

21. Selectai o imagine pe care ai pregtit-o n acest scop:

Fo rm l.D esign er.e s Fo rm l.c s J _____ 7 Solution Explorer Solution Trnag... 9

Application I 3 Im ages J Add Resou rce * ; M "\ \ ^ So lu tio n Im ageExam ple (1 project)
: ........ ' ' v. ; ,, Q ^5] im a g e E x a m p ie

Build <j .jfl Properties


bj| R eferences

Build E ve n ts 3 caS SS S S
actori.bmp

D e b ug a i] Form l .t;s
^ Form l.D esign er.e s
R e so u rc e s* - vt) F o rm l.re sx

actori
2 Program .cs
Settings

22. Selectai controlul P ictureB ox. n panoul P roperties, acionai butonul cu


eticheta (...) din dreapta proprietii Image. n dialogul S e le ct R esource
vei selecta Project Resource File i ncrcai imaginea pe care ai adus-o
la resursele proiectului.

23. Declarai un cmp privat zoom, n clasa Forml. El reprezint cantitatea cu


care se incrementeaz dimensiunile controlului la fiecare apsare a
butoanelor:

private int zoom;

24. Tratm evenimentul C lick pentru butonul cu textul Zoomln. Acionai dublu
click asupra lui. Se deschide Editorul de Cod. Scriei codul evideniat cu
Bold, n handler-ul de eveniment:

private void buttonl_Click(object sender, Ev'entArgs e)


{
zoom = 2;
// Limea i nlimea dup o apsare de buton
int W = pictureBoxl.Size.Width + zoom;
int H = pictureBoxl.Size.Height + zoom;
C apitolul 7. C ontroalele W indows F orm s 233

// Are loc actualizarea dimeniunilor prin


// modificarea proprietii ClientSize
pictureBoxl.ClientSize = new Size(W, H ) ;
}

25. Tratm evenimentul C lic k pentru butonul cu textul ZoomOut. Acionai


dublu click asupra iui. n handler-ul evenimentului vei scrie acelai cod, cu
singura diferen c prima linie este: zoom = - 2 ; (dimensiunile scad).

26. Compilai i rulai cu F5.

( Zoom In j [ Zoom Oul |

Prin apsarea ceior dou butoane, se obine efectul de mrire, respectiv de


micorare a imaginii.

De retinut:

Resursele adugate proiectului se integreaz n mod automat n fiierul


assembiy compilat (fiierul .exe).
Resursele sunt imagini, iconuri, sunete, sau stringuri.
Editarea resurselor se face design time cu ajutorul Editorului de
Resurse, sau runtime n mod programatic.
ntre folderele proiectului apare unul nou, numit R esources, care poate
fi vizualizat din S o lu tio n E xplorer.
Se pot elimina elemente folderul Resources, fr ca aceasta s afecteze
fiierul assembiy. La fiecare b u ild , compilatorul consult acest folder i
numai dac a aprut o versiune nou a unui fiier, acesta este integrat
n assembiy.
234 P artea a Il-a . P rogram are W indow s cu V isual C # Express E dition r.
. '15?;.'

Manipularea runtim e a resurselor

Resursele se acceseaz uor din cod, deoarece mediul integrat creaz o ,?F
clas Resources, aflat n spaiul de nume Properties, iar acesta din urm se C
gsete n interiorul spaiului de nume al aplicaiei. n clasa Resources, toate
resursele se acceseaz simplu, ca oricare membru public.
lat de exemplu cum putei atribui ru n tim e unui control o alt imagine din 3 *
resursele proiectului: |j

pictureBoxl.Image = I m age.Properties.Resources.p i sica; "

Resursa pisica este un tip nou creat, pe baza unei imagini obinute dintr-un fiier
care se numea de exemplu pisica.bmp. v

Setarea iconului aplicaiei i a iconului unei forme

Ca s ataai un icon fiierului a sse m b ly (.exe) al aplicaiei, n S o lu tio n


E x p lo re r acionai dublu click pe itemul Properties. n fereastra care se deschide,
selectai A pplication, apoi selectai check box-uI Icon and manifest i alegei iconul
dorit.
Ca s ataai un icon unei forme, selectai forma n Form Designer, apoi n
fereastra Properties selectai proprietatea Ic o n i alegei un icon-ul dorit.

Clasa Im ageList

ImageList este un control care ncapsuleaz o colecie de imagini sau icon- |


uri. Imaginile se folosesc de ctre alte controale, cum este Listview, TreeView
sau Toolstrip. Principalii membrii ai clasei sunt: ~

Proprieti r.

Images Colecia de imaqini utilizate de ctre alte controale


ImageSize Dimensiunea imaginilor n colecie. Indiferent de dimensiunile
iniiale ale imaginilor, acestea se convertesc la un fomat
specificat n momentul n care se adaug la colecie
ColorDepth Valoare care indic adncimea de culoare. Valorile obinuite
sunt 5 biti (256 culori), 16 biti (high cotor), 24 bii (true cotor).

Metode

Draw{) Metod suprancrcat care deseneaz imaginile pe suprafaa


unui control. _________
C apitolul 7. C ontroalele W indows Form s 235

Aplicaia ImageListExample

Vom utiliza un control de tip ImageList ca surs de imagini pentru un control


PictureBox. Reinei c un PictureBox nu se poate conecta direct la ntreaga list
de imagini, aa cum o fac alte controale mai evoluate, ca ListView sau TreeView.
n aceast aplicaie, la fiecare acionare unui buton, se acceseaz cte o
imagine din ImageList i imaginea se afieaz n PictureBox.

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


ImageListExample.

2. Aducei din Toolbox pe suprafaa formei un control de tip PictureBox i


un buton.

3. Cutai opt imagini de mrime medie i salvai-le


ntr-un folder oarecare.

4. Selectai controlul PictureBox. n panoul


Properties, setai pentru proprietatea SizeMode
valoarea Strechimage. Aceasta ntinde
imaginea pe toat suprafaa controlului. Setai ca
imagine iniial pentru proprietatea image, una
dintre cele 8 imagini pe care le-ai pregtit pentru
acest proiect:

5. Selectai butonul i stabilii pentru proprietatea


T e x t, valoarea Urmatoarea Imagine

6. Din Toolbox, tragei pe suprafaa formei un


control de tip ImageList. n mod automat, n fray-ul Ferm Designer-ului
apare numele referinei: imageListl.

7. Apsai click pe sgeata mic din colul dreapta sus al numelui


imageListl n designer tray. Stabilii ImageSize la valorile 32 i 32 i
adncimea de culoare la valoarea Depth32Bit.

.: a Z ImageUst Tasks
' ! ; V # imageListl :....................... v~ z
; | ......................... Image Si2e 32,^32

Image Bit Depth Depth32Bit

8. Alegei Choose images. n Editorul Coleciilor de Imagini, adugai pe rnd


cte o imagine la ImageList. Cifrele din stnga reprezint poziiile
imaginilor n colecie. Poziiile se pot schimba, acionnd sgeile:
236 Partea a Il-a . P rogram are W indow s cu V isu al C# E xpress E dition

Members: caine.jpg properties:

f i
M Bl girafa.jpg
I2 s a

i l E
gorila.jpg
pisica.jpg
0
| sa
* tfgru.jpg
^ 'i i i
i: .Hotnt caine.jpg
ja,,
I 5s a urs.jpg
\ 6 a s veverita.jpg
vultur.jpg
i2 J E 2
ia

Cancel

9. Declarai n clasa F o rm l, n fiierul Form1.cs, cmpul privat- count. Acesta


reprezint indexul imaginii din ImageList, care se afieaz la un moment
dat n P ictu re B o x:

private int count = 0;

10. Vom trata evenimentul C lick pentru buton. Acionai dublu click pe
suprafaa lui. Scriei codul evideniat cu B old, n handler-ul de eveniment:

private void buttonl_Click(object sender, EventArgs e)


{
// Atribuim proprietatii Image imaginea din
// ImageList corespunztoare indexului count % 8
pictureBoxl.Image = imageListl.Images[count % 8];
count++;
}

11. Compilai i lansai n execuie cu F5.


C apitolul 7. Controalele W indows F orm s 237

Imaginea se schimb la fiecare click.

De reinut:

Obiectele de tip Im ageList rein colecii de imagini, care se utilizeaz de


ctre alte controale.
Toate imaginile se formateaz n mod automat la aceleai dimensiuni i
adncimi de culoare precizate n momentul adugrii n Im ageList,
indiferent de formatul iniial.
Imaginile se acceseaz cu ajutorul operatorului de indexare. De exemplu,
imageListl.images [3]; reprezint a patra imagine din colecia referit
de imageListl. Atenie la acest exemplu! n colecia aceasta trebuie s
existe cel puin 4 imagini, altfel images [3] duce la aruncarea unei
excepii.

fi C ontrolu l L istV ie w

L istV iew este un control complex, destinat afirii unei liste de itemi.
Panoul din dreapta al aplicaiei Windows Explorer implementeaz un
ListV iew . Control Panel este un alt exemplu cunoscut de ctre toat lumea.
Pentru fiecare item din list controlul afieaz un text i un icon.
Itemii se pot afia n cinci moduri diferite. Cele cinci moduri sunt determinate
de valorile pe care le poate avea proprietatea View, a clasei L istV iew .

Modurile de afiare ntr-un ListView

Valorile posibile ale proprietatii view determin cele cinci moduri de


afiare. Aceste valori sunt:

Largelcon - Afieaz iconuri mari (32x32 pixeli), cu text dedesupt,


aliniate de la stnga la dreapta i de sus n jos____________
238 P artea a Il-a . P rogram are W indow s cu V isu al C# E xpress E dition

Smalllcon - Afieaz iconuri mici (16x16 pixeli), cu eticheta n dreapta


List - Afieaz iconuri mici (16x16 pixeli), cu eticheta n dreapta.
Itemii sunt aranjai n coloane, fr header de coloan.
Details - Fiecare item apare pe o singur linie. Informaiile
suplimentare despre item sunt date de subitemi. Subitemii
sunt aranjai pe colane diferite, pe aceeai linie. Coloana
cea mai din stnga conine un icon mic i un text.
Tile - Afieaz iconuri mari, cu text n dreapta acestuia,
reprezentnd informaiile din subitemi.

IMPORTANT !
Fiecare item ntr-un control ListView, este o instan a clasei ListViewltem.

Principalii membri ai clasei ListView


Clasa conine numeroase metode, proprieti i evenimente, graie crora
are multiple caliti, lat cteva :
Suport selecia simpl i multipl a itemilor.
Tratatnd corespunztor a evenimentele de la tastatur i mouse, itemii
pot deveni activi, declannd aciuni ca deschidere de fiiere, lansare de
aplicaii, etc.
Se poate folosi pentru afiarea informaiilor dintr-o baz de date, a
informaiilor din fiiere, de pe disc, sau a informaiilor din aplicaii.

Principalii membri ai clasei s u n t:

P roprieti:
Items - Depoziteaz colecia de obiecte de tip ListViewltem
care reprezint subitemii.
Collumns - Returneaz colecia de obiecte de tip ColumnHeader
care sunt afiate n ListViewControl.
View - Permite specificarea modului de afiare a itemilor n list
LargeImageLi s t - Indic obiectul imageList care conine iconurile folosite
la afiarea itemilor, atunci cnd proprietatea View are
valoarea Largelcon .
SmallImageList - Indic obiectul ImageList care conine iconurile folosite
atunci cnd proprietatea View are oricare alt valoare n
afar de Largelcon %
MultiSelect - Cnd este setat true, se pot selecta mai muli itemi odat

Metode: J
C l e a r {) - nltur toti itemii din control
BeginUpdate() - Prima metod suspend redesenarea controlului
EndUpdate() ListView la fiecare adugare a unui item n situaia n
care se adaug un mare numr de itemi.
- Se apeleaz a doua metod dup terminarea operaiei de
update, pentru a permite controlului s se redeseneze.
C apitolul 7. C ontroalele W indows F orm s 239

Evenim ente:
C o lu m n C lic k - Se declaneaz la click pe header-ul unei coloane
SelectedlndexChanged - Se declaneaz cnd utilizatorul selecteaz sau
deselecteaz un item

Aplicaia ListViewExample
Proiectul afieaz o list titluri de cri, n toate modurile de afiare:
Largelcon, Smalllcon, List, Tile, Detail. n modul Detail, fiecare item (carte) are cte
doi itemi suplimentari, afiai n coloana a doua i a treia: numele autorului i
editura care a publicat cartea. De asemenea, tot n modul Detail este disponibil
opiunea de Grid.

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


ListViewExample.

2. Tragei din T o o lb o x pe suprafaa formei un control de tip L istV iew un


control G rou pB ox, cinci controale R adioB utton, un C heckB ox i un
buton de apsare i aranjai-le astfel:

O "Wi: . ; ...0

I
j] Modufi Afiare

I O Large icons

I O Tie
O Sm al icons

? O u*t
O Detai
5 O 2n d

j lere ]

3. Cutai cteva fiiere de tip imagine cu coperi de cri i salvai-le ntr-un


folder oarecare. Notai-v pentru fiecare carte, titlul, autorul i editura.

4. Aducei din T o o lb o x dou controlate de tip Im ageList. n fray-ul Form


Designer-ului a p a rimageListl i imageList2. Ele reprezint referinele
spre colecia de icon-uri mici necesare n modurile Smalllcon, List i
Detail, respectiv spre colecia de icon-uri mari, necesare n modurile
Largelcon i Tile.
5. Setai pentru imageListl, dimensiunile (16, 16) i adncimea de culoare
8 bii. Setai pentru imageList2 dimensiunile (48, 48) (putei decide i
alte dimensiuni) i adncimea de culoare 32 de bii:
240 Partea a II-a. P rogram are W indow s cu V isu al C # E xpress E dition

.....
Q p im a g e L is t l j & im age U stZ (
j Im a g e Size

j Im a g e Bit D e p th j D e p th 32 B it

&ror'lst
6. Adugai aceleai imagini n ambele obiecte de tip Im ageList, acionnd
Choose images.

7. Dorim s populm controlul L istV iew la ncrcarea formei. Facei dublu


click pe suprafaa formei, pentru a trata evenimentul Load. n corpul
handler-ului evenimentului, scriei codul evideniat n B old:

private void Forml_Load(object sender, EventArgs e)

// Controlul listViewl preia coleciile de iconuri


// mici i de iconuri mari
listViewl.SmallImageList = imageListl;
listViewl.LargeImageList = imageList2;

// Suspendm redesenarea listei ct timp adugm


// itemi
listViewl.BeginUpdate();

// Pentru modul Detail, adugm trei coloane avnd


// n header-e textele "Crti", Autor, "Editura".
// Limile coloanelor sunt 150, 100 i 110 i
// alinierea orizontal
listViewl.Columns.Add("Carti C#", 150,
HorizontalAlignment.Left);
listViewl.Columns.Add(A u t o r " , 100,
HorizontalAlignment.Left);
listViewl.Columns.Add("Editura", 110,
HorizontalAlignment.Left);

// Adugm primul item n list. Este un obiect de


// tip ListViewltem
ListViewltem itl = new ListViewltem();

// Indexul icon-ului din listlmagel i listlmage2.


// Putei avea mai muli itemi cu acelai index,
// deci cu acelai icon
i t l .Imagelndex = 0;

// Textul itemului
itl.Text = "C# 2008 Code Book";

// Crem cei doi subitemi. Putei avea orici


// subitemi pentru un item, dar avei grij s
// creai tot attea coloane.
C apitolul 7. C ontroalele W indow s F orm s 241

i t l .Subltems.A d d ("Jrgan Bayer");


i t l .Subltems.Add("Addison-Wesley 2007") ;

// Adugm itemul n controlul ListView


listViewl.Items.Add(itl);

// Se creaz al doilea item, n acelai mod


ListViewItem it2 = new ListViewItem();
i t 2 .ImageIndex = 1;
it2.Text = "Beginning C# 2008";
it2.Subltems.Add("Karl Wats o n " ) ;
it2.Subltems.Add("WROX 2008");
listViewl.Items.Add(it2);

// Creai ceilali itemi ca mai sus


II...

/ / A m terminat adugarea de itemi.


II Acum permitem controlui s se redeseneze
listViewl.EndUpdate();
}

8. Acionai dublu ciick pe radio butonul cu eticheta Large Icons. Tratm


evenimentul C heckedC hanged. n Editorul de Cod, scriei:

private void radioButtonl_CheckedChanged(object sender,


EventArgs e)
{
// Proprietatea View primete valoarea Largelcon.
// Largelcon este un membru al enumerrii View
listViewl.View = View.Largelcon;

// Dezactivm csua de validare pentru Grid.


II Efectul Grid e posibil numai n modul Detail
checkBoxl.Enabled = false;
}

9. Acionai dubiu ciick pe radio butonul cu eticheta Tile. n corpul handler-ului


de eveniment, scriei codul:

listViewl.View = View.Tile;
checkBoxl.Enabled = false;

10. Acionai dublu ciick pe radio butonul cu eticheta Small Icons. n corpul
handler-ului de eveniment, scriei codul:'

listViewl.View = View.Smalllcon;
checkBoxl.Enabled = false;

11. Acionai dublu ciick pe radio butonul cu eticheta List. n corpul handler-ului
de eveniment, scriei:
242 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress E dition

listViewl.View = View.Tile;
checkBoxl.Enabled = false;

12. Acionai dubiu click pe checkbox-ul cu eticheta Grid. Tratm evenimentul


C heckedC hanged. n handler-ul de eveniment, scriei codul marcat cu
B old:

private void checkBoxl_CheckedChanged(object sender,


EventArgs e)
{
// Dac tocmai s-a selectat checkbox-ul
if {checkBoxl.Checked)
{ // atunci punem griduri.
listViewl.GridLines = true;
}
else
{ II Dac tocmai s-a deselectat controlul
// scoatem gridurile
listViewl.GridBines = false;
)
}

13. Acionai dublu click pe butonul Ieire. Tratm evenimentul C lick. n corpul
metodei de tratare, scriei:

Application.Exit(); // Ieire din aplicaie

14. Compilai proiectul i rulai cu F5.

La rulare, se obine:
Vedere Large Icons:
83CariiC# [ IU

Moduri Afiare
C# 2008 CodeBeginnino Ctt C# 3.0 Urdeashed
Bock 2008 Large Icons

O T0e

O Small Icons

O List

O Detaii

Visual C# 2 X 8 Visual C8 .NET Visual Studio


| lesiie l
2008
C apitolul 7. C ontroalele W indow s F orm s 243

Vedere n modul Tile:


fi*

Pro C# 2008 3.5 Platfcxm


I A.ndt T ro e b e n
I APRESS 2007
Moduri Afiare -

- Visual Ctt 2008 O Large Icons


~ DirK hcrch-lovv'iki
Tfe
d-iior,-Wesley 200?
O Sm a llc o n *
" * Visual Ctt .NET
jp Jamet Fo/all O Liti
tnf'orn\! f 2008
O DeM
Visual Studio 2008
Lan cwers
'VJdi.ori-Vv'a*-lftv201)7
| W P F in 24 hours
I R o d E iie n b e iC le w s
I vWdicon-w'eclev2008

Vedere n modul Detail cu gridurile activate:

CartiCtt _ Autor Edtura


* * C 3 2008 Code Book Jrgen Bayer A d dson-W esley 2.
Beginning Ctt 2008 Karli W atson W R O X 2008 Moduri Afiare
@ C t f 3.0 Unleashed Joseph M ayo Inform!! 2007
O Larselcom
Essential Ctt 3.0 Mark Micheefc frformIT 2007
T Head first Ctt Andrew SteSman A P R E S S 2007 O TJe

P Pio Ctt 2008 3.5 Platform Andrew T roelten A P R E S S 2007 O S m e ilc a i*


Visual Ctt 2008 Dirk Frischalowski Addison-W esley Z.
James Foxal
O Utl
Visual C tt.N ET IrrformIT 2008
Visual Studio 2008 Lars Powers Addeon-W esley Z. DetaO
W P F in 24 hours Rob Eisenberg Addis on-Wesley 2..
0 Grid

Ieire

Celelalte moduri de afiare funcioneaz de asemenea n mod corespunztor.

Observaii:
t

In multe situaii itemii nu se introduc n mod manual. Acetia pot fi ncrcai


din fiiere XML, sau din baze de date, aa cum vom vedea n capitolele
urmtoare.
n proiectul acesta, itemii au fost adugai programatic. Este una dintre
cele mai simple variante, dar nu unica. Mai exist i alte variante de
adugare programatic a itemilor, pe care le putei gsi n literatura de
specialitate.
244 Partea a II-a. P rogram are W indow s cu V isual C # E xpress E dition

Adugarea design time a itemilor ntr-un ListView

Selectai controlul ListV iew . n fereastra P roperties apsai butonul cu


eticheta (...) din dreapta proprietii Item s. Se deschide dialogul ListViewltem
Collection Editor. Apsai butonul Add pentru a aduga itemi.

Members: ListViewltem: {} properties:


_0j UstVtewItem: {}
ListViewltem: ()
B ..1
T ListViewltem: Text
ToolTipText
'Jsetem S tyiePor True
El Behavior
Group (none)
Im agelndax j~ 1 (none)
tmageKey I ] (none)
g ta tetm ao e in d e x 1 | (none)
S Data
Subitem s (Collecbon)
Tag
B Display
Inden tC o u n t 0

I <* I n ci

n panoul din dreapta, selectai Subitems i apsai butonul din dreapta. n dialogul
ListViewSubitem Collection Editor, adugai pe rnd subitemii necesari pentru
fiecare item:

UitVtewSubltem Collectioiv editor v C f \g j 1


U stV T ew 5 u b Item : (B e g in n in g C # 2CQ8}- p r ,.,

. 1 j ListViewSubitem: (Karl Watson)- :a H Bv. .


2j ListViewSubitem: (W RO X 2008} El D ata
S0 T ag

B M ise
BackColor | i W in d ow
S Font M ic ro s o ft S a n s Serif;
ForeColor m W in d o w T e x t
, Name L is tV ie w S u b Ite m 3
Text B e g in n in g C # 2 0 0 8

|~ Add j | Remove |

[~ OK ) j~ Cancel j

De retinut:

> Dac implementai afiarea Detail, atunci este nevoie s adugai coloane
(obiecte de tip ColumHeader).
> Itemii sunt obiecte diferite de tip ListViewltem.
> Numrul subitemiior trebuie s coincid cu numrul coloanelor.
C apitolul 7. Controalele W indows F orm s 245

Probleme propuse
1. Aducei urmtoarea facilitate aplicaiei ListViewExample: la apsarea unui
buton, se activeaz opiunea de selectare a ntregului rnd, atunci cnd
utilizatorul face click pe un item n modul Dtail.

2. n aplicaia ListViewExample, introducei cte un mic icon care preced


textul n fteacfer-ul fiecrei coloane (modul Detaif).
Indicaie: Utilizai constructorul adecvat al clasei C o l u m n H e a d e r , astfel:

ColumnHeader c = new ColumnHeader(3);


// 3 este indexul iconului
c . T e x t = "C# 2 0 0 8 "
l i s t V i e w l . C o lu m n s .A d d ( c ) ;
// etc

3. * Creai o aplicaie care preia ntr-un L istV ie w informaiile despre fiierele


i folderele care se gsesc ntr-un folder dat. Folderul se alege cu ajutorul
controlului prdfinit F olderB row serD ialog.

4. Creai o aplicaie care permite editarea etichetelor itemilor unui L istV iew .

C ontro lu l TreeView

Controlul afieaz o colecie ierarhic de elemente care se numesc noduri.


Fiecare nod este o instan a clasei TreeNode. Proprietatea Nodes a controlului
memoreaz aceast colecie de noduri.
Nodurile se creaz programatic relativ simplu. Creai un proiect de tip
Windows Forms i tratai evenimentul Load generat de form (dublu click pe
suprafaa ei), apoi scriei codul:

private void Forml Loadobject sender, EventArgs e)


{
// Instaniem un TreeView
TreeView tw = new TreeView();

// Crem un prim nod cu eticheta "Baieti"


TreeNode tnl = new TreeNode();
tnl.Text = "Baieti";

// Adugm nodul n control


t w .N o d e s .A d d (tnl);

// Crem al doilea nod cu eticheta "Fete"


TreeNode tn2 = new TreeNode(J ;
tn2.Text = "Fete ;

// Adugm nodul n control


tw.Nodes.Add(tn2);
246 P artea a II-a. P rogram are W indow s cu V isual C # E xpress E dition

// Adugm controlul pe form


t h i s .Controls.Add(tw);
1

Crearea ierarhiilor

Fiecare nod ntr-un TreeView poate fi printe pentru alte noduri.


Se pot crea ierarhii arborescente cu oricte niveluri. Modificm exemplul anterior,
prin adugarea de noduri child nodurilor Baieti' i Fete":

// Instaniem un TreeView
TreeView tw = new TreeView();
// Stabilim poziia pe form i dimensiunea controlului:
tw.Location = new System.Drawing.Point(12, 12);
tw.Size = new System.Dra w i n g .S i z e (153, 133);

// Crem un prim nod cu eticheta Baieti


TreeNode tnl = new TreeNode();
tnl.Text = "Baieti";

// Crem un nod child pentru Baieti:


TreeNode tnll;
// Referina tnnl indic nodul nou creat (cu eticheta Marius)
tnll = t n l .Nodes.Add("Marius);

// Nodul Marius va fi printe pentru alte dou noduri:


tnll.Nodes.Add("Profesie");
tnll.N o d e s .A d d ("Hobby");

// Al doilea nod child pentru Baieti:


t n l .Nod e s . A d d ("Valentin");

// Adugm nodul Baieti n control:


t w .N o d e s .A d d (tnl);
C apitolul 7. C ontroalele W indows F orm s 247

// Crem al doilea nod rdcin cu eticheta Fete:


TreeNode tn2 = new TreeNode() ;
tn 2 .Text = "Fete";
tn 2 .N o d e s .A d d ("Alina");
t n 2 .Nodes.Add("Teodora");

// Adugm nodul Fete n control


t w .N o d e s .A d d (tn2);
// Adugm controlul pe form
this.Controls.A d d (tw);

8|'||'|"7
a P E ia a
Q Marius
Profesie
Hobby
I Valenlin
1 - Fete
! Alina
j Teodora

Imaginea anterioar reprezint ceea ce se obine la rulare.

Important:
Metoda A d d () returneaz ntotdeauna o referin ia nodul nou creat.
Aceasta nlesnete adugarea de noduri child.

Accesarea indexat a nodurilor


Subnodurile care fac parte din colecia Nodes a nodului curent se pot
accesa cu ajutorul operatorului de indexare. Relum exemplul anterior. Prezentm
o alternativ de construire programatic a controlui, bazat pe accesarea indexat:

// Instaniem un T r e e V i e w
T r e e V i e w t w = n e w T r e e V i e w ();

// Stabilim poziia pe form i dimensiunea controlului:


t w . L o c a t i o n = n e w S y s t e m . D r a w i n g .P o i n t ( 1 2 , 1 2 ) ;
tw.Size = ne w S y s t e m . D r a w i n g . S i z e (153, 1 3 3 );

// Adugm n control un prim nod:


tw . N o d e s . A d d ( " B a i e t i " ) ;

// A.daugm subnodurile Mar i u s si Valentin pentru Baieti


tw.Nodes[0].Nodes.Add("Marius");
t w . N o d e s [ 0 ] . N o d e s . A d d ("Vale n t i n " );

// Adugm subnodurile Ocupaie si Hobby pentru Marius:


t w . N o d e s [ 0 ] . N o d e s [0].Node s . A d d ("Ocupaie");
t w .N o d e s [ 0 ] . N o d e s [0].Nodes.Add("Hobby");
248 Partea a II-a. P rogram are W indow s cu V isual C # E xpress Edition

// Adugm subnodurile Varsta i coala pentru Valentin:


t w.N o d e s [ 0 ] . N o d e s [ 1 ] . N o d e s . A d d (" V a r s t a " );
t w . N o d e s [ 0 ] . N o d e s [ 1 ] . N o d e s . A d d (" S c o a l a " );

// Adugm controlul pe form:


this.Controls.Add(tw);

La execuie se obine :

I 0 Marius
i Ocupaie
j Hobby
j 3 - Valentin
I - Varsta
! Scoala

Principalii membri ai clasei TreeView

Controlul TreeView are multiple capabiliti. Descriem cteva dintre acestea:

> Poate afia imagini asociate fiecrui nod.


> Poate afia opional checkbox-un asociate nodurilor.
> i poate schimba aparena setnd corespunztor proprietide stil.
> Poate rspunde la diverse evenimente, cum ar fi click sau dublu
click pe eticheta unui nod.
> Se poate folosi pentru afiarea informaiilor dintr-o baz de date, a
informaiilor din fiiere, de pe disc, sau a informaiilor din aplicaii.

Aceste caliti se datoreaz mulimii de metode, proprieti i evenimente ale


clasei. Dintre acestea menionm:

Proprieti :
Nodes - Depoziteaz colecia de obiecte de tip T r e e N o d e a
controlului. Fiecare nod are la rndului lui proprietatea
Nodes, care gzduiete propriile noduri child.
LabelEdit - Stabilete dac eticheta text a unui nod poate fi editat
CheckBoxes - Stabilete dac se afieaz un checkbox lng etichetele
nodurilor
SelectedNode - Returneaz sau modific nodul selectat.
PathSeparator - Returneaz sau seteaz stringul separator folosit In calea
spre noduri. Calea spre un nod este un set de etichete de
noduri separate prin delimitatorul P a t h S e p a r a t o r .
C apitolul 7. Controalele W indows F orm s 249

Metode:

C o l l a p s e A l l () - Colapseaz ramurile arborelui (Inversul expandrii)


B e g i n U p d a t e () - Suspend redesenarea controlului TreeView la fiecare
E n d U p d a t e () adugare a unui item n situaia n care se adaug un
mare numr de itemi.
- Se apeleaz a doua metod dup terminarea operaiei de
update, pentru a permite controlului s se redeseneze.
GetNodeAt() - Retumeaz nodul care se gsete la locaia specificat

E venim ente:

BeforeCollapse - Se declaneaz nainte, respectiv dup colapsul unui


AfterCollapse nod
BeforeExpand - Se declaneaz nainte, respectiv dup expandarea
AfterExpand unui nod

Parcurgerea prelucrarea nodurilor

Uneori trebuie s vizitai toate nodurile unui T reeV iew pentru o prelucrare
oarecare. Amiritii-v c un TreeView este o structur de date arborescent. Vei
nelege din ce cauz parcurgerea unei asemenea structuri se face cu o metod
algoritmic. Propunem o parcurgere n adncime:
*
p r i v a t e v o i d P a r c u r g T r e e V i e w ( T r e e N o d e C o l l e c t i o n noduri)
{
foreach ( T r e e N o d e n o d in n o d u r i )
{
PrelucrezNod(nod);
ParcurgTreeView(nod.N o d e s ) ;
}
}

private void PrelucrezNod(TreeNode nod)


{
// Prelucrarea dorit pentru n o d
// Aici, pentru verificare afim doar eticheta
M e s s ageBox.Show(node.Text + "\n") ;
}

p r i v a t e v o i d b u t t o n l _ C l i c k (ob j e c t s e n d e r , EventArgs e)
{
//
ParcurgTreeView(treeViewl.Nodes);
}
250 P a rtea a I l-a . P r o g r a m a r e W in d o w s cu V isu a l C # E x p re ss E d itio n

De reinut:
treviewi .Nodes reprezint colecia de noduri rdcin n arbore.
Fiecare nod din aceast colecie are la rndul lui proprietatea Nodes, care
refer nodurile de pe al doilea nivel, etc.
T r e e N o d e C o lle c tio n este un tip de date care reprezint o colecie de
obiecte T re e N o d e .

Aplicaia TreeViewExample
Proiectul pe care l propunem utilizeaz un combobox pentru selectarea
dr/Ve-urilor sistemului. n funcie de discul selectat, ntr-un control T r e e V ie w se
afieaz structura arborescent de directoare discului.

E le m e n te d e n o u ta te :
Obinerea informaiilor despre discuri cu metoda:
Drivelnfo.GetDrives()
Obinerea numelor subdirectorilor unui director specificat, cu metoda:
Directory.GetDirectories O
Parcurgerea recursiv a structurii de directoare a unui disc, n scopul
populrii controlului TreeView.

Urmai paii:

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


TreeViewExample.

2. Aducei din T o o lb o x pe suprafaa formei controalele: un L a b e i, un


C o m b o B o x , un B u tto n i un T re e V ie w i aranjai-le astfel:

3. Modificai culorile controlulului TreeView dup preferin: culoarea


fundalului (proprietatea BackColor), culoarea etichetelor (ForeColor) i
culoarea liniilor punctate (LineColor).
C apitolul 7. C ontroalele W indows Form s 251

4. Adugai directiva u s in g S y s te m . 1 0 ;

5. n fiierul Form1.cs, n corpul ciasei Forml, scriei secvenele de cod


urmtoare:

public F o r m l () // Constructoul clasei


{
InitializeComponent ();
// Populeaz comboBoxl cu toate drive-urile
Drivelnfo] drives = Drivelnfo.GetDrives();
comboBoxl.Items.AddRange(drives);
}

// Cmpuri private. Reprezint caracterul de separare


// a cii de director, respectiv litera discului
p r i v a t e char[] sep = n e w char[] { '\ \ ' };
p r i v a t e s t r i n g d r v L e t t e r = nuli;
// Deep First n structura de directoare
p r i v a t e v o i d P o p u l a t e T r e e V i e w (st r i n g p a t h ,
T r e e N o d e node)
{
string[] dirs = D i r e c t o r y . G e t D i r e c t o r i e s ( p a t h ) ;
s t r i n g [ ] auxs;
f o r e a c h ( string d i r i n dirs)
{
a u x s = d i r .S p l i t ( s e p ) ;
T r e e N o d e tn =
new TreeNode(auxs[auxs.Length - 1]);
node.Nodes.Add(tn); // Adaug subdirectorul
PopulateTreeView(dir, t n ) ;
}
}

6. Aplicaia trebuie s reacioneze la alegerea unui item n combobox. Tratm


evenimentul S electedlndexC hanged pentru comboBoxl. Pentru aceasta,
acionai dublu click pe acest control. n corpul handler-ului de eveniment,
scriei codul evideniat n bold:

private void comboBoxl_SelectedIndexChanged(


object sender, EventArgs e)
{
// Obinem textul itemului selectat n combobox
drvLetter =
c o m b o B o x l .I t e m s [ c o m b o B o x l .S e l e c t e d l n d e x ] . T o S t r i n g O ;

// Suspendm redesenarea controlului


t r e e V i e w l .B e g i n U p d a t e ();

// tergem toat colecia de noduri


t r e e V i e w l .N o d e s .C l e a r () ;
252 P a rtea a II-a . P r o g r a m a r e W in d o w s cu V isu a l C # E x p r e ss E d itio n

// Adugm eticheta drive-ului ca nod rdcin


treeViewl.Nodes.A d d (drvLetter);
drvLetter += // Concatenez caracterul 'V

// Explorarea ncepe de la rdcina drive-ului


PopulateTreeView(drvLetter, treeViewl.Nodes[0]);
treeViewl.EndUpdate{);
}

7. Acionai dublu click pe butonul Ieire. n dand/er-ul evenimentului C lick,


scriei:

Application.Exit{);

8. Compilai i rulai cu F5.

La rulare obinei:

Selectai un Disc. jcA yj I ieire

Observaie:
Cu metoda recursiv se parcurge ntreaga structur de director a drive-ului
curent. Din aceast cauz, actualizarea controlului T reeV iew este ient pentru un
disc ncrcat.

De reinut:
Clasa D i r e c t o r y din spaiul de nume S ystem .IO furnizeaz metode
statice pentru creare, copiere, mutarea, redenumire de directori.
Clasa D r i v e l n f o din spaiul de nume S ystem .lO conine metode i
proprieti pentru determinarea informaiilor referitoare la drive-uri.
Metoda t r e e V ie w l. N o d e s . C le a r () ; terge toate nodurile din
colecie.
C apitolul 7. C ontroalele W indows F orm s 253

Probleme propuse

1. Creai o aplicaie de tip WindowsForms. Forma conine un control


TreeView. Populai design time controlul cu noduri.
Indicaie: n fereastra Properties, acionai butonul cu eticheta (...) aflat
n dreapta proprietii Nodes. n dialogul TreeNode Editor, adugai noduri
apsnd butoanele Add Root i Add Child.

2. Implementai aplicaiei TreeViewExample urmtoarea facilitate: fiecare nod


are lng etichet un checkbox.

3. * Modificai aplicaia TreeViewExample de aa manier nct nici un nod


s nu se adauge n TreeView dect n momentul cnd se expandeaz
printele su n control. Un nod se expandeaz prin click pe cruciulia din
dreptul su. n felul acesta aplicaia va lucra mai rapid.

4. Im ple m enta i un file browser cu funcionalitate asemntoare Windows


Explorer. Aplicaia trebuie s afieze n panoul din dreapta fiierele aflate
n directorul care este selectat n panoul din stnga. De asemenea, la
dublu click pe un fiier executabil n panoul din dreapta, acesta s se
lanseze n execuie.
Indicaie: Utilizai un SplitContainer. n panoul din stnga aducei un
control TreeView, iar n cel din dreapta un ListView. Pentru obinerea
fiierelor dintr-un director oarecare, apelai metoda
D i r e c t o r y .G e t F i i e s (). Pentru lansare n execuie, utilizai metoda
S y s t e m . D i a g n o s t i c e .P r o c e s s . S t a r t () .

C ontroalele W eb B ro w s e r i S tatusS trip

Dac v-ai gndit s integrai un browser Web n aplicaia dumneavoastr,


atunci cu Visual C# Express Edition 2008 aceasta este o sarcin simpl, deoarece
mediul include un control de tip WebBrowser.

Aplicaia WebBrowserExample

n acest proiect utilizm un controlde tip W ebBrowser, un control


StatusStrip pentru vizualizarea ncrcrii paginiii curente i un ToolStrip pentru
butoane i bara de navigare. Urmai paii:

1. Creai un nou proiect de tip Windows Forms cu numele


WebBrowserExample.
2. Pe forma aplicaiei aduceidin Toolbox un control de tip ToolStrip, un
control de tip StatusStrip i un control de tip W ebBrowser.
254 Partea a II-a. P rogram are W indow s cu V isual C # E xpress Edition

3. Selectai controlul ToolStrip. Adugai pe el un Labei, un TextBox i patru


butoane. Pentru fiecare buton, acionai click drept i alegei DisplayStyle,
apoi Text, pentru a afia text n loc de imagine.

4. Selectai controlul StatusStrip. Acionai click drept i alegei un


ProgressBar.

5. Selectai controlul WebBrowser. n fereastra Properties atribuii


proprietii Dock valoarea FUI i proprietii URL adresa:
http://www.google.com. Setai textele pentru butoane i aranjai totul astfel:

6. Tratm evenimentul Click pentru butonul Search. Acionai dublu click pe


buton. n corpul metodei handler, scriei:

private void toolStripButtonl_Click(object sender,


EventArgs e)
{
// ncarc pagina de la adresa specificat
webBrowserl.Navigate(toolStripTextBoxl.Text);
}

7. Tratm evenimentul Click pentru butonul Stop. Acionai dublu click pe


buton. n corpul metodei handler, scriei:

private void toolStripButton2_Click(object sender,


EventArgs e)
{
// Oprete ncrcarea paginii
w e b B r o w s e r l .S t o p ();
C apitolul 7. Controalele W indows F orm s 255

8. Tratm evenimentul C lick pentru butonul Back. Dublu click pe buton. n


corpul metodei de tratare, scriei:

private void toolStripButton3_Click(object sender,


EventArgs e)
{
// Revenire la pagin aanterioar
webBrowserl.G oBack();
}

9. Tratm evenimentul C lick pentru butonul Refresh. Dublu click pe buton. n


corpul metodei de tratare, scriei:

private void toolStripButton4_Click(object sender,


EventArgs e)
(
// Rencrcarea paginii de la URL-ul curent
w e b B r o w s e r l .R e f r e s h ();
}

10. n progress ba r-u ljn te g ra t n S ta tu s S trip dorim s vizualizm progresul


ncrcrii paginii. n acest scop, tratm evenimentul ProgressC hanged
pentru controlul W ebBrow ser. Selectai controlul i acionai dublu click pe
acest eveniment n fereastra P roperties. Introducei codul:

private void webBrowserl_ProgressChanged(object sender,


WebBrowserProgressChangedEventArgs e)
{
// Seteaz M a x i m u m la numrul total de bytes pe
// care l ocup documentul care se descarc
toolStripProgressBarl.Maximum =
(int)e.MaximumProgress;
// Seteaz V a l u e la numrul de bytes care au fost
// downloadai pn n prezent
t o o l S t r i p P r o g r e s s B a r l .V a l u e =
(int)e.CurrentProgress;
}

11. n momentul n care documentul este descrcat, dorim s ne asigurm c


progress bar- ul este la valoarea maxim. Tratm evenimentul
D ocum entC om pleted declanat de WebBrowser cnd documentul este
complet descrcat. Dublu click pe acest eveniment n P roperties. n
metoda de tratare, introducei codul:

private void webBrowserl_DocumentCompleted(


object sender, WebBrowserDocumentCompletedEventArgs e)
(
toolStripProgressBarl.Value =
toolStripProgressBarl.Maximum;
256 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress Edition

12. Compilai i rulai cu F5.

La rulare, aplicaia ncarc n mod automat pagina stabilit design time prin
proprietatea u r l . n fereastra de navigare putei introduce oricarea alt adres:

: URL: http://www.microscft.corn Search Stop Back Refresh

Observaii:
>

Dac lucrai n V isual C# E xpress E dition 2005, atunci controlul


W ebB row ser nu se gsete n mod implicit n T oolbar. Aceasta nu este o
problem, pentru c el exist ca i component .NET i l putei aduce n
T oolb a r cu un click dreapta pe suprafaa liber de jos, apoi selectai
Chose Item s... iar n tab-ul .NET Framework Components, alegei W eb
B row ser.

Clasa W e b B ro w se r are metode prin care implementai aciunile specifice


ale unui browser: navigare, rencrcare, ntoarcere la URL-ul anterior i
aa mai departe.
i
C apitolul 7. C ontroalele W indows F orm s 257

Integrarea WindowsMediaPlayer n aplicaii

Suntem siguri c v-ai ntrebat dac este greu s implementai player-e video
sau audio. Nu este uor. ns exist exist o cale mai simpl de a avea toate
acestea, prin integrarea componentei COM, W in d o w sM e d ia P la ye r n aplicaia
dumneavoastr.
Ca s vedei cum se procedeaz, vom face urmtorul proiect:

Aplicaia WindowsMecfiaPiayerExampie

Aplicaia utilizeaz componenta W indow s M edia P la y e r i un control de tip


T o o lS trip cu 5 butoane. Rolul butoanelor este acela de a efectua aceleai operaii
ca i butoanele implicite ale controlului. Ne vom servi i de dialogul prdfinit
O penF ileD ialog pentru alegerea unui fiier audio sau video de pe disc.
Urmai paii:

1. Creeai un nou proiect de tip Windows Forms.

2. Pe suprafaa designerului plasai un control de tip T o o lS trip , pe care


adugai apoi cinci butoane care afieaz text. Etichetai cele cinci butoane
astfel: Open, Start, Stop, Pause, Resume.

3. Plasai pe suprafaa formei un control de tip O penF ileD ialog.

4. W indow s M edia P la ye r nu este disponibil n T o o lb o x n mod implicit, dar


poate fi adus acolo manual. l aducei cu un click dreapta pe suprafaa
liber de jos, apoi selectai Chose Items... Iar n fab-ul COM Components,
alegei W indow s Media Player. n continuare, plasai componenta pe
suprafaa cfes/'gner-ului i setai-i proprietatea D ock la valoarea FUI i
proprietatea Name la valoarea wmp.
258 P artea a Il-a . P rogram are W indow s cu V isual C # E xpress Edition

5. Tratm evenimentul C lic k pentru butonul Open. Acionai dublu click pe


buton i scriei In metoda handler.

private void toolStripButtonl_Click(object sender,


EventArgs e)
{
// Dac s-a ales un fiier media i s-a apsat O K
if (openFileDialogl.ShowDialogO =
D i a l o g R e s u l t .OK)
{
// Playerul nu va executa play n mod automat
// la ncrcarea fiierului
w m p .s e t t i n g s .a u t o S t a r t = f a l s e ;

// Se ncarc fiierul ales de utilizator


wmp .U R L = o p e n F i l e D i a l o g l .F i l e N a m e ;

6. Tratm evenimentul C lic k pentru butonul Start. Acionai dublu click pe


buton i introducei codul:

private void toolStripButton2_Click(object sender,


EventArgs e)

// Player-ul ruleaz fiierul ncrcat


w m p .C t l c o n t r o l s . p l a y ();
}

7. Tratm evenimentul C lic k pentru butonul Stop. Dublu click pe buton i 0


introducei codul:

private void toolStripButton3_Click(object sender,


EventArgs e)
{
// Oprete rularea
w m p .C t l c o n t r o l s .s t o p ();

8. Tratm evenimentul C lic k pentru butonul Pause. Dublu click pe buton. n j#


metoda de tratare introducei codul:

private void toolStripButton4_Click(object sender,


EventArgs e)
{
// Pauz. La un nou apel play(), redarea continu
// din aceast poziie n fiier
w m p .Ctlcontrols . p a u s e ();
}
C apitolul 7. C ontroalele W indow s F orm s 259

9. Tratm evenimentul C lick pentru butonul Resume. Dublu click pe buton. n


metoda de tratare introducei codul:

private void toolstripButton5_Click(object sender,


EventArgs e)
{
// Redarea se reia din poziia n care s-a ajuns
// la ultimul apel p a u s e < )
w m p .C t l c o n t r o l s . p l a y ();
}

10. Compilai i rulai cu F5.

Putei rula att fiiere audio ct i video.

Observaie:
Controalele adugate manual au aceleai funcii cu cele ale butoanelor
implicite. A fost un exerciiu pentru cazul n care vrei s mascai bara standard i
s utilizai propriile controale pentru manevrarea player-ului.
260 Partea a Il-a . P rogram are W indow s cu V isual C # E xpress E dition

C apitolul 8

Desenare n .NET cu Visual C#


GDI+ (Graphics Device Interface) este o interfa de programare a
aplicaiilor integrat sistemelor de operare Microsoft Windows XP i Windows
Server 2003.
Aplicaiile de tip Windows deseneaz elemente grafice cu ajutorul bibliotecii
de clase GDi+. O interfa pentru dispozitive grafice, aa cum este GDI+, permite
programatorilor s deseneze pe dispozitive grafice: ecran, scanner, imprimant, cu
ajutorul acelorai funcii, fr s trebuiasc s in seama de detaliile unui
dispozitiv de afiare particular.
Se pot desena linii, curbe, figuri geometrice, text, imagini. Clasele GDI+ se
gsesc n marea lor majoritate n spaiul de nume S ystem .D raw ing. Dintre
acestea, clasa S yste m .D ra w in g .G ra p h ics este cea mai utilizat.

Clasa G raphics
Clasa definete o suprafa de desenare GDI+. Metodele sale deseneaz pe
aceast suprafa, iar biblioteca GDI+ tie s trimit imaginea pe dispozitivul grafic
(monitor, imprimant, sau altceva).

Principalele metode ale clasei Graphics

C l e a r () - Cur suprafaa de desenare i o umple cu o culoare


de fundal specificat
D r a w A r c () - Deseneaz un arc de elips
D r a w l m a g e () - Deseneaz o imagine la o locaie dat
D r a w L i n e () - Deseneaz un segment specificat prin capetele sale
D r a w E l l i p s e () - Deseneaz o elips specificat printr-un dreptunghi
care o mrginete
D r a w R e e t a n g l e () - Deseneaz un dreptunghi
D r a w S t r i n g () - Deseneaz un text la o locaie specificat
F i l l E l l i p s e () - Umple interiorul unei elipse cu ajutorul unei pensule
(obiect de tip B rush)
F i l l R e c t a n g l e () - Umple interiorul unui dreptunghi cu ajutorul unei
pensule

Clasa nu rspunde la evenimente findc nu are membri de tip event. Dar folosete
evenimentul P aint al controalelor pentru a desena pe suprafaa lor.

Penie p e n tru desenarea form e io r


Desenm cu ajutorul unui obiect de tip G raphics. Obiectul se obine n dou
moduri:
C apitolul 8. D esenare in .N E T cu Visual C# 261

1. Prin intermediul parametrului de tip P a in tE ve n tsA rg s al handler -ului


evenimentului Paint.
2. Cu ajutorul metodei CreateGraphics (), motenit de ctre toate
controalele de la clasa de baz C ontrol.

Detaliem cele dou cazuri:

Cazul 1.
Creai un proiect nou de tip Windows Forms. Tratm evenimentul P aint al
formei. Selectai forma i Tn fereastra P roperties acionai dublu click pe
evenimentul Paint. Scriei codul:

private void Forml_Paint(object sender, PaintEventArgs e)


{
// Peni de culoare roie i grosime 20
Pen p = new P e n (Color.Blue, 20);

Rectangle r = new Rectangle(new Point(50, 50),


new Size(200, 100));
e.Graphics.DrawRectangle(p, r ) ;
p .Dispose();

Compilai i rulai cu F5. Pe form s-a desenat un dreptunghi.

Handler-ului evenimentului Paint are un parametru e de tip P aintE ventA rgs.


Acesta returneaz un obiect de tip G raphics prin proprietatea Graphics:
e.Graphics.

IM P O R T A N T !
Pentru desenarea liniilor i a curbelor, avei nevoie de un obiect de tip
G raphics i un obiect de tip Pen (peni). Obiectul G raphics furnizeaz metodele
care deseneaz, iar obiectele de tip Pen depoziteaz atribute ale liniei, cum ar fi
culoarea, grosimea i stilul.
262 Partea a I l-a . P rogram are W indow s cu V isual C# Express Edition

Reinei c este o practic bun aceea de a elibera resursele deinute de


obiectul Pen, cu metoda D i s p o s e O , n momentul n care nu mai avei nevoie
de el.

Cazul 2.
Metoda C r e a t e G r a p h i c s ( ) , se regsete n toate clasele derivate din
C o ntro l. Retumeaz un obiect de tip G raphics. Este nevoie de aceast metod
cnd nu dorii s foloii un eveniment P aint pentru a desena.
Realizai un nou proiect de tip Windows Forms. Pe form plasai un buton.
Acionai dublu click pe buton pentru tratarea evenimentului C lick.
n handier-ul evenimentului introducei secvena de cod evideniat cu B old:

private void buttonl_Click(object sender, EventArgs e)


{
// Obinem un obiect G r a p h i c s
Graphics g = t h i s . C r e a t e G r a p h i c s ();

// Fabricm o peni
Pen p = n e w Pen(Color.Red, 3);

// Desenm o linie
g .D r a w L i n e ( p , n e w P o i n t ( 2 0 , 30), new Point(280, 30));

// Desenm un arc definit de dreptunghiul (50, 50, 200,


// 100). Unghiul de nceput e 0, iar cel de sfrit 360.
// Aceasta nsemn elips
g.DrawArc(p, 50, 50, 200, 100, 0, 36 0 ) ;

// Schimbm stilul peniei (linie punctat) i desenm


// un dreptunghi
p . D a s h S t y l e = S y s t e m . D r a w i n g . D r a w i n g 2 D .D a s h S t y l e . D o t ;
R e c t a n g l e r = n e w R e c t a n g l e ( n e w P o i n t ( 5 0 , 50),
n ew Size(200, 100));
g .D r a w R e e t a n g l e ( p , r );

p . D i s p o s e () ;
}

La click pe butonul Deseneaz, pe suprafaa formei se deseneaz figurile:


C apitolul 8. D esenare n .N E T cu V isual C# 263

Deseneaz

Observaii
Un arc este o poriune a unei elipse. Ca s desenai o elips, apelai
metoda D r a w E l l i p s e () . Parametrii metodei D r a w A r c O sunt
aceeiai cu cei ai metodei D r a w E l l i p s e () , cu diferena c
D r a w A r c O necesit un unghi de start i unul de baleiere, lat cum
desenai o elips:

G r a p h i c s g = t h i s . C r e a t e G r a p h i c s ();
P e n p = n e w P e n ( C o l o r .Red, 3) ;
Rectangle r = new Rectangle(new Point(50, 50),
new Size(200, 100));
g.DrawEllipse(p, r ) ;
p.Dispose();

Metodele de desenare ale arcelor i elipselor primesc ca parametri


coordonatele dreptunghiului care le ncadreaz. Metodele sunt
suprancrcate. De exemplu, putei nlocui apelul:
g . D r a w A r c ( p , 50, 50, 200, 100, 0, 3 6 0 ) ; CU apelul
g.DrawArc(p, r, 0, 36 0 ) ; unde r este dreptunghiul definit
anterior.

Poligoane
; Desenarea unui poligon se face foarte simplu, prin apelul metodei
- D r a w P o l y g o n Q . Metoda are ca parametri un obiect de tip P e n i un tablou de
puncte:

G r a p h i c s g = t h i s .C r e a t e G r a p h i c s ();
P e n p = n e w P e n ( C o l o r .Red, 3);
j P o i n t f ] p t = { n e w P o i n t ( 1 9 0 , 90), n e w P o i n t ( 1 4 0 , 130),
I n e w P o i n t ( 1 5 0 , 20 0 ) , n e w P o i n t ( 6 0 , 100) };
// Deseneaz un poligon cu patru vrfuri
g.DrawPolygon(p, p t ) ;
j p.Dispose();
264 Partea a Il-a . Program are W indow s cu V isual C # E xpress Edition

Dac ne folosim de evenimentul Click al butonului n aplicaia anterioar, atunci la


click pe Deseneaz, avem:

Pensule p e n tru um plerea form elor

Figurile nchise se deseneaz cu penie. Interiorul lor se umple cu pensule.


Pensulele sunt obiecte de tip B rush.
Biblioteca GD!+ ofer cteva clase care definesc pensule: S o iid B ru sh ,
H atchB rush, T e xtu re B ru sh , Line arG rad ien tB ru sh , i P athG radientB rush.
Clasa S o iid B ru s h este definit n spaiul de nume S ystem .D raw ing.
Celelalte pensule sunt n spaiul de nume S ystem .D raw ing.D raw ing2D .
Cel mai simplu mod de a nva, este de a lucra cu aceste pensule. Vom realiza o
aplicaie ca model.

Aplicaia BrushesExam ple

Aplicaia umple trei elipse cu pensule diferite: o pensul solid, una de


haurare i una gradient liniar. n dreapta formei se va umple un dreptunghi cu o
pensul de tip T e xtu re B ru sh , care utilizeaz ca element de umplere o imagine.

Urmai paii:

1. Creai un nou proiect de tip W indow s F orm s A p p lic a tio n , cu numele


BrushesExample.

2. n fiierul Form1.cs, n clasa Forml, introducei la seciunea directivelor


using, secvena:

using System.Drawing.Drawing2D;
C apitolul 8. D esenare n .N E T c u Visual C# 265

3. Tratm evenimentul P aint pentru form. Selectai forma. n fereastra


P roperties, acionai dublu click pe evenimentul P aint. n corpul handler-
ului introducei codul:

private void Forml_Paint(object sender,


PaintEventArgs e)
{
Pen p = new P e n (Color.Red, 3);

// Crem un dreptunghi pentru elipse


int x = 10, y = 10, width = 200, height = 100;
Rectangle r = new Rectangle(x, y, width, height);

// Crem o pensul solid


SolidBrush s = new SolidBrush(Color.Aquamarine);

// Umplem elipsa cu pensula solid


e .Graphics.FillEllipse(s, r ) ;

y = 120;
r = new Rectangle(x, y, width, height);
// Crem o pensul de haurare
HatchBrush h =
new HatchBrush(HatchStyle.DiagonalCross,
Color.Azure, C o l o r .B lack);

,// Umplem elipsa cu pensula de haurare


e.Graphics.FillEllipse(h, r ) ;

y = 230;
r = new Rectangle(x, y, width, height);

// Crem o pensul gradient liniar


LinearGradientBrush Ig = new LinearGradientBrush(r,
Color.Aqua, Color.BlueViolet,
LinearGradientMode.Horizontal);

!! Umplem elipsa cu pensula gradient liniar


e .Graphics.FillEllipse(Ig, r) ;

x = 230; y = 15; width = 250; height = 310;


r = new Rectangle(x, y, width, he ig h t ) ;

// Crem o pensul de textur


TextureBrush t =
new TextureBrush(Image.FromFile("pisica.jpg"));

// Umplem dreptunghiul cu pensula de textur


e.Graphics.FiiIRect a n g l e (t, r ) ;
p .Dispose () ;
266 Partea a II-a. P rogram are W indow s cu V isual C# E xpress Edition

4. Compilai, rulai cu F5.

La rulare, avem:

Observaii:
f

Constructorii claselor de tip brush primesc ca argumente culori, stiluri, etc,


prin intermediul membrilor anumitor enumerri. Ai remarcat enumerrile
C oior, L inearG radientM ode, HatchStyle.

* Constructorul TextureBrush((Image.FromFile ("pisica.jpg")) ;


ncarc o imagine. Dac se specific doar numele fiierului imagine,
atunci acesta este cutat n folderul n care se gsete fiierul assembly,
adic /b in /D e b u g sau /bin/R elease.

D esenarea te x tu lu i

GDI+ furnizeaz cteva clase care se ocup cu desenarea textului. Clasa


G raphics are n acest scop mai multe metode Drawstring ( ) . V vei acomoda
cu utilizarea acestora, urmrind exemplul de mai jos:

Aplicaia DrawStringExample
Ca s desenai cu metodele Drawstring () trebuie s pregtii un font i o
pensul. Aplicaia testeaz dou dintre metodele D r a w S t r i n g O . Prima scrie un
text la o locaie specificat de un punct, iar a doua scrie un text ncadrat ntr-un
dreptunghi.
C apitolul 8. D esenare n .N E T cu V isual C# 267

Urmai paii:

1. Creai un nou proiect de tip W indow s F o rm s A p p lic a tio n , cu numele


Dra wStringExample.

2. Tratm evenimentul P aint pentru form. Selectai forma. n fereastra


P roperties, acionai dublu click pe evenimentul P aint. n corpul handler-
ului introducei codul:

private void Forml_Paint(object sender,


PaintEventArgs e)
(
String s = "Da u u n r e g a t p e n t r u u n ca l " ;

// Crem un font preciznd familia, dimensiunea


/ / i stilul, apoi o pensul solid
F o n t f = n e w F o n t ( " A r i a l " , 22, F o n t S t y l e .B o l d ) ;
S o l i d B r u s h b = n e w S o l i d B r u s h ( C o l o r .R e d ) ;

// Punctul colului stnga sus al stri.ngului


P o i n t F p t = n e w P o i n t F (20.OF, 30.OF);

// Deseneaz stringul
e .G r a p h i c s . D r a w s t r i n g (s , f, b, pt) ;

f l o a t x = 1 0 0 . OF, y = 1 0 0 . OF, w i d t h = 2 0 0 . OF,


h e i g h t = 8 0 . OF;
R e c t a n g l e F r = n e w R e c t a n g l e F (x, y, w i d t h , h e i g h t ) ;

// Deseneaz dreptunghiul pe ecran


Pen p = new P e n (Color.Black);
e .G r a p h i c s .D r a w R e c t a n g l e (p, x, y, width, height);

// Formatm stringul. Aliniere centru


// (in dreptunghi)
S t r i n g F o r m a t s t F = n e w S t r i n g F o r m a t ();
stF.A l ignment = StringAlignment.Center;
f = n e w F o n t ( " T i m e s N e w r o m a n " , 24,
F o n t S t y l e .I t a l i c ) ;

// Desenez textul in dreptunghiul r


e .G r a p h i c s . D r a w S t r i n g ( s , f, b, r, stF);

p . D i s p o s e ();

3. Compilai i rulai cu F5.

La rulare, obinei:
268 Partea a H -a. Program are W indow s cu V isual C # E xpress E dition

Dau un regat pentru un cai

Dau im regat
pentru un cal

Observaii:
t

* Clasa S trin g F o m a t are proprietatea A l i g n m e n t , care permite s setai


alinierea textului n dreptunghiul specificat.
* P o in t F i R e c ta n g le F sunt structuri similare P o in t i R e c ta n g le , cu
diferena c admit coordonate reale.
A doua metod DrawStringO constrnge stringul s se ncadreze n
dreptunghiul specificat i l .trunchiaz n aa fel nct cuvintele individuale
nu se frng.

De reinut:

s Cu ajutorul bibliotecii GDI+ se scriu aplicaii care deseneaz pe


dispozitive grafice (ecran, imprimante),
v Clasa S yste m .D ra w in g .G ra p h ics este nucleul metodelor de desenare,
v' Pentru a desena o curb, avei nevoie de o peni (obiect de tip Pen), iar
pentru a umple sau haura o curb nchis, avei nevoie de o pensul
(obiect de tip B rush).
/ Obiectele de tip G raphics, cu care apelai metodele Draw, se obin n
dou moduri:
1. Din parametrul de tip P aintE ventA rgs al metodei de tratare a
evenimentului Paint.
2. Prin apelul metodei C re a te G ra p h i.e s ( ) .
V Textul se deseneaz cu metodele D rawStringQ ale clasei G raphics.
C apitolul 8. D esenare n .N E T cu V isual C# 269

Probieme propuse

1. S presupunem c n handler-ul evenimentului P a in t desenai pe


form un text. Stringul care trebuie desenat este itemul pe care s-a
' fcut click ntr-un L istb o x. Cum forai redesenarea formei (declaarea
evenimentului P aint) la click pe acel item ? Realizai o aplicaie care
implementeaz aceast cerin.
Indica ie: n handler-ul eveniementului S electe d ln d e xC h a n g e d al
controlului L istB o x, preluai textul necesar i foai evenimentul P aint
cu metoda t h i s . i n v a l i d a t e (). Aceasta invalideaz toat
suprafaa formei i oblig redesenarea.

2. Exist patru versiuni ale metodei DrawEllipse ( ) . Testai-le pe toate


ntr-un mic proiect.

3. Realizai un proiect n care vei desena icon-uri cu ajutorul celor dou


metode D ra w ic o n () i vei afia imagini, utiliznd cteva versiuni
diferite ale metodei D ra w lm a g e ( ) .

4. Utilizai metoda G r a p h ic s . R o ta te T r a n s fo r m ( ) , pentru a roti un


string-uri i figuri geometrice care au fost desenate cu metodele
D ra w ( ) .

5. Realizai un mic proiect care utilizeaz metodele D ra w P ie ( ) ,


D ra w P o ly g o n ( ) , F i l l P i e () i F i l l P o l y g o n ( ) .
270 P artea a II-a. P rogram are W indow s cu V isu al C # E xpress E dition

Capitolul 9

X M L cu C#

XML (e x te n s ib le M arkup Language) este un limbaj folosit pentru


descrierea datelor. Menirea XML este de a oferi un format standard, cu ajutorul
cruia aplicaii diferite, rulnd pe calculatoare diferite, pot s citeasc datele, s le
procese i s le scrie. Sistemele de calculatore i bazele de date conin date n
formate incompatibile. Datele XML se depoziteaz n format text. Aceasta a oferit
o cale de a depozita i de a transmite datele n mod independent de software-ul i
hardware-ul folosit.
XML specific date, dar i forma n care datele sunt organizate. Formatul
XML este folosit pentru depozitarea informaiilor din documente care conin
cuvinte, pentru meninerea listelor de preuri pe site-urile Web, detaliiile posf-urilor
de pe bloguri. XML este vehiculul prin care se trimit cantiti mari de informaie prin
Internet. Datele schimbate ntre serviciile Web i aplicaiile clienilor sunt XML.

Sintaxa X M L
Spre deosebire de HTML, XML este destinat depozitrii i transportului
datelor i nu afirii datelor. Tag-urile XML nu sunt predefinite. Trebuie s definii
dumneavoastr aceste tag-uri. Un fiier XML este un fiier cu text.

< ? x m l v e r s i o n = " l .0" e n c o d i n g = " u t f - 8 " ?>


<biblioteca>
<carte nrvol ="12">
< t i t l u > O a m e n i si s o a r e c i < / t i t l u > jgg
<autor>John Steinbeck</autor>
</carte> **'
<carte nrvol ="7">
< t i t l u > D a r u l lui H u m b o l d t < / t i t l u > L
<autor>Saul Bellow</autor>
</carte>
</biblioteca> J;

E lem entele sunt ceea ce scriei ntre parantezele unghiulare. Exemplu:


biblioteca, carte, titlu, autor, sunt elemente. Primul element, < ? x m l W.
v e r s i o n = " i .0 "
e n c o d i n g = " u t f - 8 " ?> indic versiunea XML cu care estejjf
conform acest document i c e conform cu standardul de codificare Unicode
UTF-8. t
A trib u te le descriu elementele. J|

S intaxa pentru un element este:

<nnne e l e m e n t nume_atribut = " v a .lo a .re _ a tr ib u t" >


Coninutul elementului .r|
</nume element>
-,?a M
i
C apitolul 9. X M L cu O l 271

De exemplu, 12 i 7 sunt atributele elementelor carte. Atributele pot s lipseasc.


Comentariile n document se scriu astfel: < ! C o m e n t a r i u >

Criteriile pe care trebuie s le ndeplineasc un document valid XML sunt:

Documentul are exact un singur element root. n cazul de fa, elementul


root este b i b l i o t e c a . Acesta ndeplinete rolul de container pentru restul
datelor.
Pentru fiecare element start" trebuie s existe un element corespunztor
final . Exemplu: < c a r te > i < / c a r t e > .
Elementele nu se pot suprapune. Documentul urm tor este invalid:

<biblioteca>
<carte>
<titlu>Iarna vrajbei noastre</carte>
< / titlu>
</biblioteca>

C lase .N E T p e n tru X m l

Clasele .NET care lucreaz cu XML se gsec n spaiul de nume


System.Xml. Documentele XML au o structur arborescent. Trebuie s conin
ntotdeauna un unic element root. Acesta la rndul lui, conine atribute, valori, alte
elemente, i aa mai departe. Clasa XmIDocument se bazeaz pe aceeai idee.
Un document se obine prin instanierea clasei XmIDocument. Obiectul are
proprietatea ChildNodes, care este o colecie referine la nodurile child. Fiecare
element al coleciei este un obiect de tip XmINode. Fiecare obiect de tip XmINode,
are ia rndul lui proprietatea ChildNode. Astfel, deoarece n fiecare nod se menin
referine spre nodurile child. se poate explora ntregul document.

Citirea in fo rm a iiilo r dintr-un d o cu m e n t X M L

Un document XML poate ndeplini rolul unei baze de date pentru aplicaia
dumneavoastr. Aplicaiile citesc deseori informaii din asemenea fiiere XML. Este
important, pentru c dac dorii s modificai acele informaii, schimbai coninutul
fiierului XML i nu e nevoie de refacei aplicaia.
Aplicaiile .NET pot s i scrie n fiiere .xml. De exemplu, dac setrile pe
care le face utilizatorul n aplicaie trebuie fie persistente, atunci e o idee bun s le
salvai ntr-un document XML.

Vom lucra n continuare cu clasa XmIDocument, pentru citirea datelor dintr-un


document (fiier) XML.
272 Partea a Il-a , Program are W indow s cu V isual C # E xpress E dition

Aplicaia Xm lExam ple

Aplicaia citete date din fiierul E l evi, x m l i le afieaz n mai multe


controale. ntr-un control de tip L is tB o x se afieaz numele elevilor, iar n alte trei
controale de tip T extB ox, se afieaz coala, ciasa i profilul clasei pentru elevul
care a fost selectat n list box.
Urmai paii:

1. Creai un nou proiect de tip W indow s F orm s A p p lic a tio n , cu numele


XmlExample.

2. Aducei pe forma aplicaiei un control de tip L is tB o x , trei controale de tip


TextB ox, dou butoane, un G roupB ox, patru controale Labei i aranjai-le
astfel:

Elevi
: Informaii
i

; coala:!

i Clasa: j

i Profil: i""

Incarca XML Ieire

3. Vom edita fiierul XML. Mediul integrat include un editor de fiiere XML.
Acesta se invoc acionnd click drept n S o lu tio n E x p lo re r pe titlul
proiectului, apoi Add, i N ew Item... n dialogul care apare, alegei din
panoul Template, iconul XML File. Completai cmpul Name cu Elevi.xml.
n editor scriei urmtorul document:

< ? x m l v e r s i o n = " l .0" encoding="ut'f-8" ?>


<absolventi>
<elev>
<nume>Ardelean Eugen</nume>
<scoala>C.N. Liviu Rebreanu</scoala>
<clasa>a Xll-a A</clasa>
<profil>matematica-informatica</profil>
</elev>

<elev>
<nume>Costea Andrei</nume>
<scoala>C.N. Andrei Muresanu</scoala>
<clasa>a IX-a C</clasa>
<profil>stintele naturii</proil>
</elev>
C apitolul 9. X M L cuC # 273

<alev>
<nume>Nicoara Alina</nume>
< s c o a l a > G r . Sc. I n d u s t r i a l n r l < / s c o a l a >
<clasa>a Xl-a B</clasa>
<profil>telecomunicatii</profil>
</elev>
< /ab 3o l v e n ti>

Dup ce ai editat i ai salvat, copiai fiierul Elevi.xml din folderul


proiectului, n folderul /bin/D ebug.

4. n seciunea se directive a fiierului fiierul F orm f.cs, in tro d u ce i:

using System.Xml;

5. Declarai dou cmpuri private n clasa F o rm l:

II d reine ntregul document X M L


private XmlDocument d = n u l i ;

// e l e v i reine colecia de noduri child a


// nodului curent.
p r i v a t e X m l N o d e L i s t e l e v i = nuli;

6. Tratm evenimentul C lick pentru butonul Incarca Xml". n fereastra


F ro p e rtie s acionai dublu click pe buton. n corpul fand/er-ului introducei
codul:

private void buttonl_Click(object sender, EventArgs e)


{
d = new XmlDocument(); II Creeaz un document XML
d.Load("Elevi.xml"); // ncarc fiierul

// Returneaz colecia de elemente (noduri) "elev"


elevi = d.SelectNodes("absolveni/elev");

II Parcurge elementele " e l e v


for (int i = 0; i < elevi.Count; i++)
{
/ / n colecia e l e v i , nodurile se acceseaz
II indexat. Pentru fiecare elev, se selecteaz
// nodul " n ume"
XmlNode elev =
e l e v i .I t e m ( i ) .S e l e c t S i n g l e N o d e ( " n u m e " ) ;

// Numele elevului se adaug n list


l i s t B o x l .I t e m s .A d d ( e l e v . I n n e r T e x t ) ;
i/
}

7. La selectarea unui nume n list, dorim s afim n controalele T e xtB o x


informaiile referitoare la acel nume.
274 P artea a Il-a . P rogram are W indow s cu V isual C # E xpress E dition

Tratm evenimentul S electedlndexC hanged pentru L istB o x. Selectai


controlul i n fereastra P roperties, facei dublu click pe eveniment. n
metoda de tratare, introducei codul evideniat:

private void listBoxl_SelectedIndexChanged(


object sender, EventArgs e)
{
// Se obine indexul numelui selctat
int index = listBoxl.Selectedlndex;

// Se selecteaz lista de elemente " e lev"


e l e v i =* d . S e l e c t N o d e 3 ( " a b s o l v e n t i / e l e v " ) ;

/ / n colecia e l e v i se acceseaz cel cu indexul


// i n d e x . Apoi se selecteaz subelementul " c o a l a "
XmlNode nume =
e l e v i .I t e m ( i n d e x ) .S e l e c t S i n g l e N o d e (" c o a l a " );

// Textul aferent elementului " c o a l a "


t e x t B o x l .T e x t = n u m e .I n n e r T e x t ;

// Operaiile se repet pentru " c l a s a " i " p r o f i l "


XmlNode clasa =
e l e v i .I t e m ( i n d e x ) . S e l e c t S i n g l e N o d e ( " c l a s a " ) ;
t e x t B o x 2 .T e x t = c l a s a .I n n e r T e x t ;
XmlNode profil =
e l e v i .I t e m ( i n d e x ) . S e l e c t S i n g l e N o d e ( " p r o f i l " ) ;
t e x t B o x 3 .T e x t = p r o f i l .I n n e r T e x t ;
}

8. Compilai i rulai cu F5.

La rulare, dup acionarea butonului Incarca XM L:

F o rm l

Elevi

lA ideleanE uaen Informaii -


! Costea Andrei
! Nicoara Alina
i : coala: jC.N. LiviuRebreanu 1

i . Clasa: |aXII-aA !
'
Profil: matematica-informatica 1
t i
i

| Incarca XML | | Ieire |


i ........- ......... ...................... ........... - ....- .....- ..................i
C apitolul 9. X M L cu C# 275

Important!

* Clasele X m l D o c u m e n t i X m l N o d e L i s t motenesc Clasa X mlNode.


Astfel ne explicm faptul c proprietile C h i l d N o d e s i n n e r T e x t se
regsesc printre membrii ambelor clase.
* n n e r T e x t este valoarea nodului concatenat cu valorile tuturor
copiilor si.
* X m l N o d e L i s t reprezint o colecie ordonat de noduri.
Metoda X m l N o d e l t e m ( i n t i) a clasei X m l N o d e L i s t returneaz
nodul aflat la indexul i.

D escrcarea fi ie re lo r X M L de pe In te rn e t

n ultimii ani, multe site-uri i bloguri expun clienilor un format XML cunoscut
sub numele RSS (Really Simple Syndication), n scopul distribuirii de coninut care
se schimb frecvent (tiri, sumarul coninutului unui site sau ntregul coninut,
posturi pe blog, etc).
Un furnizor de coninut (site, blog) public de regul un link (feed link) la care
utilizatorii subscriu cu ajutorul unor programe specializate (feed reader).
Subscrierea se face simplu, copiind link-ul din Web brow ser n feed reader. Mai
departe, coninuturile noi se descarc n mod automat, iar utilizatorul este ntiinat
cnd acest lucru se petrece. Practic, se descarc fiiere XML.
Cu .NET putei crea propriul feed reader (agregator). Nu vom face acest
lucru aici, ci vom arta ct de simplu putei descrca un fiier XML de pe Internet
sau un feed RSS.

Aplicaia DownloadXml

Aplicaia utilizeaz clasa W e b C l i e n t din spaiul de nume S ystem .N et


pentru a descrca un fiier de tip XML.

Urmai paii:

1. Creeai o aplicaie de tip Windows Forms n Visual C# Express 2008.

2. Pe forma aplicaiei, aducei din T o o lb o x un buton.

3. La seciunea directivelor, n fiierul Form1.cs, adugai directivele:

u s i n g S y s t e m . Xml;
u s i n g System.Net;

4. Tratm evenimentul C lick generat la click pe buton. Acionai dublu click


pe buton. n metoda de tratare scriei:
276 Partea a II-a. P rogram are W indow s cu V isual C # E xpress E dition

private void buttonl_Click(object sender, EventArgs e)


{
// Descrcm n stringul x m l coninutul X M L (RSS
// feed) de ia un anumit U R L
string xml = new
W e b C l i e n t ().D o w n l o a d s t r i n g ("h t t p :// n e w s .g o o g l e .c o m / "
+ "? o u t p u t = r s s " ) ;

// Crem o instan de tip X m l D o c u m e n t


X m l D o c u m e n t d o c = n e w X m l D o c u m e n t ();

// ncrcm stringul (cu coninut XML) n document


d o c .L o a d X m l ( x m l ) ;

// Salvm pe disc coninutul X M L descrcat


d o c .S a v e ("c o n t i n u t .x m l ");
}

5. Compilai i rulai cu F5.

Dup executare, vei gsi n folderui / B i n / D e b u g fiierul c o n t i n u t . x m l.

Observaie:

Pe numeroase site-uri i blog-uri vei gsi feed link-uri pentru subscriere. Iat
cteva link-uri alese aleatoriu:

http://www.preferredjobs.com/rss/rss2.asp
http://sourceforge.net/export/rss2_sfnews.php?feed
http://newsrss.bbc.c o .uk/rss/newsonline_uk_edition/world/rss.
x m l

Citirea i analiza unui do cu m ent X M L cu


X m IT e x tR e a d e r

Transportul datelor la distan se face n mod frecvent cu ajutorul stream-


urilor.
Clasa X m I T e x t R e a d e r este un instrument foarte rapid de accesare stream-
urilor de date XML. Clasa reprezint un cititor (reader), care se deplaseaz n
stream doar nainte (forward only), citete documentul nod dup nod i nu modific
stream-ul. Reader-ul v permite s v deplasai progresiv n documentul XML i s
examinai fiecare nod, cu elementul, atributele i valoarea sa.
Propunem o aplicaie care ilustreaz o parte dinte capabilitile acestei
clase.
C apitolul 9. X M L cu C # 277

Aplicaia Xm ITextReaderExam ple

Programul C# de mai jos folosete clasa X m ITextR eader pentru a citi un


document XML aflat pe disc. Documentul este citit nod cu nod, apoi este
reconstituit i se afieaz pe ecran.
Urmai paii:

1. n Visual C# creeai un proiect de tip consol cu numele


XmITextReaderExample.

2. Editai fiierul crti.xml cu urmtorul coninut:

< ! --Citire fiier XML-->


<biblioteca>
Ccarte ISBN="18S-383-537">
<Titlu>Amintiri din copilarie</Titlu>
< P r e t > 1 3 .2 0 < / P r e t >
<Autor>Ion Creanga</Autor>
</carte>
</biblioteca>

3. n fiierul Program.cs introducei codul:

using System;
using System.Xml;

class Program
1
s t a t i c v o i d M a i n ( s t r i n g [] args)
{
// Crem un r e a d e r (instan a clasei) i
// ncrcm fiierul
XmITextReader reader =
new XmITextReader ("crti.xml");

// Citim pe rnd toate nodurile din document


while ( r e a d e r . R e a d ())
{
// n funcie de tipul nodului curent
switch (reader.NodeTypej
{
// Dac nodul este un element
c a s e X m l N o d e T y p e .E l e m e n t :
C o n s o l e . W r i t e ("<" + r e a d e r . N a m e ) ;
C o n s o l e . W r i t e L i n e (">");
break;

II Afim textul din fiecare element


c a s e X m l N o d e T y p e .T e x t :
278 Partea a Il-a . P rogram are W indow s cu V isual C# E xpress E dition

Console.WriteLine (" " +


reader.Value) ;
break;

// Afim "sfritul" elementului


c a s e X m l N o d e T y p e .E n d E l e m e n t :
C o n s o l e . W r i t e ("</" + r e a d e r . N a m e ) ;
C o n s o l e . W r i t e L i n e (">");
break;
}
}
} // M a i n O
}

4. Compilai i rulai cu F5.

La rulare, pe ecran se va afia:

De reinut:
Metoda R e a d () a clasei x m ir e x tR e a d e r citete i returneaz
urmtorul nod din stream.
Proprietatea N o d e T y p e a clasei x m l N o d e este o enumerare ai crei
membri reprezint tipurile de noduri din document. Studiai aceast
enumerare pentru a vedea c exist mai multe tipuri de noduri dect n
acest exemplu.
Cu ajutorul clasei x m l T e x t R e a d e r obinei coninutul XML dintr-un fiier
sau dintr-un stream. n plus, are calitatea c v permite s analizai i s
prelucrai acest coninut.
C apitolul 9. X M L cu C# 279

Crearea c o n in u tu lu i X M L cu X m IT e x tW rite r
$

Clasa X m I T e x t W r i t e r ofer o cale rapid cu care putei genera fiiere sau


stream-uri cu coninut XML. Clasa conine un numr de metode i proprieti cu
care se genereaz coninut XML. Pentru a le folosi creai un obiect de tip
X m I T e x t W r i t e r , apoi adugai pe rnd entiti XML obiectului. Exist metode cu
care putei aduga orice tip de coninut XML. Aplicaia pe care urmeaz utilizeaz
cteva dintre aceste metode.

Aplicaia XmITextWriterExample

Vom crea un fiier cu coninut XML. Urmai paii:

1. Creeai o aplicaie de tip consol n Visual C# Express Edition.

2. n fiierul Program.cs, introducei codul:

u s i n g System;
using System.IO;
using System.X m l ;

public class Program


{
// Fiierul n care se scrie coninutul XML
private string filename = "c o n i n u t . x m l ";

public static v o i d Main()


{
// Crem obiectul de tip X m I T e x t W r i t e r
XmITextWriter writer =
n e w X m I T e x t W r i t e r ( f i l e n a m e , null);

// Folosim indentarea tag-urilor


w r i t e r .F o r m a t t i n g = F o r m a t t i n g .I n d e n t e d ;

// Scriem un comentariu XML


w r i t e r .W r i t e C o m m e n t (" C r e e a r e fiier X M L " ) ;

// Scriem primul element (root) .


w r i t e r . W r i t e s t a r t E l e m e n t (" l i b r r i e " );

// Scriem elementul c a r t e (child pentru


// librrie)
w r i t e r . W r i t e S t a r t E l e m e n t (" c a r t e " );
// Scriem un atribut pentru c a r t e
w r i t e r .W r i t e A t t r i b u t e S t r i n g (" I S B N " ,
"186-383-523");
280 Partea a II-a. P rogram are W indow s cu V isual C # Express E dition

// Titlul crii
w r i t e r .W r i t e S t a r t E l e m e n t (" T i t l u " );
writer.WriteString("Amintiri din copilrie");
w r i t e r . W r i t e E n d E l e m e n t ();

// Preul si autorul crii


w r i t e r . W r i t e E l e m e n t S t r i n g ("P r e t " , " 1 3 .20") ;
w r i t e r .W r i t e S t a r t E l e m e n t {" A u t o r " );
w r i t e r . W r i t e S t r i n g ("Ion C r e a n g a " ) ;

// Scrie tag-ul de sfrit pentru elementul


// c a r t e
w r i t e r .W r i t e E n d E l e m e n t () ;

// Scrie tag-ul de sfrit pentru elementul


// l i b r r i e
w r i t e r . W r i t e E n d E l e m e n t ();

// Scrie XML n fiier si nchide w r i t e r


w r i t e r .F l u s h ();
w r i t e r .C l o s e ();

// Afim coninutul XML si pe ecran


X m l D o c u m e n t d o c = n e w X m l D o c u m e n t ();

/1 Pstrm spaiile albe pentru lizibilitate


d o c .P r e s e r v e W h i t e s p a c e = t r u e ;
// ncrcm fiierul
d o c .L o a d ( f i l e n a m e ) ;

//Scriem coninutul XML pe ecran


C o n s o l e . W r i t e ( d o c .I n n e r X m l ) ;

C o n s o l e .R e a d L i n e ();
} // M a i n ()
}

3. Compilai i rulai cu F5.

n folderul /b in /D e b u g vei gsi fiierul continut.xml. Acelai coninut se afieaz i


pe ecran:
C apitolul 9. X M L cu C# 281

De retinut:

Clasa xmlTextwriter ofer o cale programatic de a crea coninut XML


Metodele clasei au nume intuitive.
De exemplu, w r i t e r . W r i t e S t a r t E l e m e n t ( " t i t l u " ) ; scrie n
obiectul writer < t i t l u > .
Cu W r i t e S t r i n g () scriei textul asociat elementului curent.
Exist i alte metode i proprieti corespunztoare altor-entiti XML.
Acestea se utilizeaz n mod similar. Merit efortul s le explorai.

Probleme propuse

1. Realizai o aplicaie care utilizeaz controale text box pentru a introduce


datele personale ale clienilor unei bnci. Datele clienilor se vor salva ntr-
un fiier n format XML.

2. Realizai o aplicaie care deschide un fiier XML i afieaz ntr-un textbox


concatenarea tuturor textelor asociate elementelor child ale elementului
root.

3. Realizai o aplicaie de tip consol care descarc un feed RSS de pe


Internet i listeaz numele tuturor elementelor din coninutul XML.

4. Realizai o aplicaie care citete coninutul XML dintr-un fiier i cu ajutorul


clasei X m lT e x tR e a d e r i afieaz ntr-un L is tB o x toate elementele XML.

5. Realizai o aplicaie care salveaz ntr-un fiier cu coninut XML informaii


despre produsele unui magazin. La repornirea aplicaiei, aceste informaii
se pot ncrca de ctre aplicaie pentru a fi afiate n controale.
282 Partea a Il-a . Program are W indow s cu V isual C # E xpress Edition

Partea a III - a

Baze de date
Scopul acestei pri a lucrrii este acela de a v ajuta s accesai bazele de date
relaionale cu C#.

Capitolul 10

Baze de date i ADO.NET. Noiuni introductive


Capitolul are urmtoarele obiective:

O scurt prezentare a sistemului de gestiune pentru baze de date


reaionale MS SQL Server.
Generaliti despre sistemele de gestiune a bazelor de date relaionale.
Primele noiuni despre tehnologia ADO.NET.
Crearea unei baze de date n Visual C# 2008 Express Edition.
Interogarea bazei de date cu ajutorul Query Designer.

In stru m en te de lucru

Instrumentele software pe care le vom utiliza n lucrul cu bazele de date sunt:

Visual Cit Express Edition 2008 (VCSE).


M icrosoft SQL Server Express Edition 2005 (SSE).

Ambele instrumente funcioneaz pe platforma M icrosoft .NET versiunea 3.5.


Sunt versiuni free, puternice, destinate s lucreze mpreun. n momentul cnd
instalai VCSE, avei opiune de instalare i pentru SSE.
SSE, este un subset al serverului de baze de date Microsoft SQL Server
2005. Acesta din urm este unul dintre cele mai avansate sisteme de gestiune a
bazelor de date ( SGDB ) existente. Dei SSE nu include toate capabilitile SQL
Server 2005, este perfect funcional i utilizabil n aplicaii industriale. Suport
procesarea online a tranzaciilor (OLAP), poate s gestioneze baze de date mai
mari de 4 Gb i admite sute de conexiuni concurente.
Cnd instalai SSE, vei avea de fapt dou versiuni ale serverului: SQL
Server Express Edition i SQL Server Express Compact Edition 2005. Acesta
din urm, este o versiune cu mai puine faciliti, fiind destinat s gestioneze baze
de date locale. n momentul n care construiie o baz de date n VCSE, avei
opiunea de a alege unul dintre cee dou servere.
C apitolul 10. B a ze de date i A D O .N E T . N oiu n i introductive 283

S G D B -u ri - n o iu n i generale

Sistemele de gestiune ale bazelor de date, aa cum numele indic, se


ocup cu crearea i ntreinerea bazelor de date. O baz de date este o colecie de
informaii structurate. Bazele de date poate nmagazina mari cantiti de informaie
care poate apoi s fie accesat i modifica' n mod eficient de ctre utilizatori prin
intermediul SGDB-urilor.
Un SGDB admite multiple baze de date. Utilizatorii obin informaii din bazele
de date scriind interogri (query) care se adreseaz serverului de baze de date.
Acesta le execut, efectund operaii specifice asupra bazei de date i ntoarce
utilizatorului un set de rezultate. Operaiile obinuite sunt: de modificare a datelor,
de introducere de noi date, de tergere.
SQL (Structured Query Language} este limbajul cu care trebuie s ne
adresm unui SGDB care opereaz cu baze de date relaionale. n aceast lucrare
vom presupune c cititorii au cunotine elementare referitoare la acest limbaj.
Un S istem de G estiune a B azelor de Date R e la io n a le (SGDBR) este un
SGDB bazat pe m o d e lu l relaional. Datele sunt depozitate n tabele. ntre tabele
exist relaii, iar relaiile se memoreaz de asemenea n baza de date.

Calitile
i SGDBR-urilor

Sistemele de gestiune a bazelor de date asigur depozitarea i regsirea


datelor. n raport cu alte forme de pstrare a datelor, au afu-uri care le fac
inegalabile:

Viteza m are a o p e ra iilo r.


Operaiile asupra datelor (cutare, sortare, modificare) sunt foarte
rapide.

C om pacteaz in form aia.


Bazele de date lucreaz cu cantiti uriae de date. Acestea se
memoreaz pe spaii relativ reduse.

A sig u r secu rita te a datelor.


Datele sunt foarte bine protejate mpotriva oricrui acces neautorizat.

n tre in e datele.
Un SGDB ine evidena fiecrui fragment de informaie. Utilizatorii nu
trebuie s se preocupe acest aspect.

C ontroleaz redundana datelor.


Previn crearea de duplicate muitiple ale acelorai date, care ar duce la
ocuparea unui volum mare pe disc.

Previne in co n s is te n a datelor.
284 P artea a III - a. B aze de date

Nu permite utilizatorului operaii care distruge logica bazei de date. n


acelai timp, cnd un SGDB elimin date redundante, aceast
operaie se face cu pstrarea consistenei datelor.

A s ig u r a to m icita te a o p e ra iilo r.
Operaiile elementare, dar i grupurile de operaii (tranzaciile) se
garanteaz fie c vor fi complet executate, fie c nu vor avea nici un
efect. n oricare dintre situaii, baza de date rmne ntr-o stare
consistent.

Furnizori de baze de date relaionale

Pe pia exist multe SGDB-uri. O s amintim doar cteva firme


productoare importante:
Oracle, cu SGDB-ul Oracle. Deine recordul de vnzri n acest moment.
IBM cu produsele DB2 i In fo rm ix.
M ic ro s o ft cu SQL S erver 2005.
S ybase, cu SGDB-ul Sybase.

Exist i alte firme ale cror sisteme de gestiune a bazelor de date au un segment
de pia bine delimitat, dar mult mai restrns dect a celor menionate.
In acest punct trebuie s adugm rolul tot mai important pe care l are n
acest moment SGDB-ul MySQL. Se utilizeaz ca free software, sub GNU General
Public Licence (GPL). Este foarte popular ndeosebi pentru aplicaii Web, fiind
disponibil pentru mai multe sisteme de operare.

Tehnologia A D O .N E T - introducere

Aproape toate aplicaiile software interacioneaz cu baze de date. Este


nevoie de un mecanism prin care aplicaiile se conecteaz i utilizeaz bazele de
date. Pentru aplicaiile .NET, acest mecanism se numete ADO.NET.

Caracteristicile tehnologiei ADO.NET

ADO.NET este format dintr-un subset al B ib lio te c ii de Clase .NET, folosite


n programare pentru accesarea surselor de date, n special a bazelor de date
relaionale.
nainte ca platforma .NET s existe, n programarea aplicaiilor pentru
sistemele W indows se utilizau urmtoarele tehnologii de accesare a bazelor de
date: ODBC {Open Database Connectivity), O LE DB {Object Linking and
Embedding, Database) i ADO {ActiveX Data Objects). ADO este o colecie de
obiecte pentru accesarea surselor de date.
Capitolul 10. B aze de date i A D O .N E T . N o iu n i in troductive 285

Pentru compatibilitate cu SGDB-uri mai vechi, ADO.NET include n


continuare ODBC i OLE DB, ns ADO.NET nu este ADO.
ADO.NET este o tehnologie complet nou de acces la date. Este parte
integrant a platformei .NET i nu este format din obiecte ActiveX. Raiunile
pentru care Microsoft a pstrat cuvntul ADO n numele ADO.NET in de ideea c
interfaa de utilizare a celor dou tehnologii este oarecum asemntoare.
ADO.NET faciliteaz dezvoltarea de aplicaii mai performante cu baze din
urmtoarele considerente:

1. Accesui deconectat ia bazele de date


ADO.NET este conceput s permit att a ccesul c o n e cta t ct i
d e co n e cta t la bazele de date. Imaginai-v c v-ai conectat prin intermediul unei
aplicaii la un server de baze de date, aflat undeva la distan n reea. Deschidei
o conexiune, citii datele, modificai datele i la sfrit v deconectai. Acesta este
m o d e lu l conectat. Dezavantajul este c n tot acest timp comunicai prin reea
direct cu serverul care trebuie s menin conexiunea i s execute interogrile.
Dac ne gndim c poate fi vorba de sute sau mii de utilizatori care transfer
cantiti mari de date, atunci nelegem c n .m odelul conectat, utilizat cu vechile
tehnologii, pot s survin suprancrcri ale serverului i ale traficului n reea, un
consum mare de resurse i ncetinirea sau blocarea aplicaiilor.
In m o d e lu l deco n e cta t datele sunt trimise de la server i sunt stocate local
la client ntr-o structur de date numit dataset. Clientul opereaz doar asupra
datelor din acest dataset, iar cnd a terminat, datele schimbate se trim it la server,
acolo unde se gsete adevrata baz de date. Astfel, serverul este eliberat de
sarcina de a menine conexiunile n mod permanent i poate servi mai muli cu
clieni. Pe partea clientului de asemenea, toate operaiile se desfoar mai rapid.

2. integrarea XML.

ADO .NET este strns legat de XML. XML este folosit intern de ADO.NET ca
s menin datele n cfafasef-uri i s rein relaiile i constrngerile ntre tabele.
Mai mult, suportul pentru XML este integrat in ADO.NET. Se pot produce scheme
XML, se pot transmite date cu ajutorul documentelor XML.

A rh ite c tu ra A D O .N E T

ADO.NET are dou componente centrale:

1. F u rn iz o rii de date (data p ro v id e r)


2. S e turile de date (datasets)

1. Furnizorii de date
Un furnizor de date (data provider) asigur conectarea la o surs de date
(data source). Sursa de date poate fi un fiier text, un document XML, o baz de
date, etc. Totodat un furnizor de date suport accesul la date i manipularea
286 P artea a III - a. Baze de date

datelor. Este legtura ntre aplicaia dumneavoastr i sursa de date. De regul


sursa de date este o baz de date i atunci un furnizor de date asigur legtura
ntre aplicaie i sistemul de gestiune a bazei de date respective.
Un furnizor de date se compune dintr-un numr de obiecte ale unor clase
specializate. Aceste clase sunt definite n interiorul unor spaii de nume speciale.
Tabelul prezint cteva dintre spaiile de nume n care sunt grupate componentele
.NET:

S paiul de num e D escriere


System.Data Clase, interfee, delegri care definesc arhitectura
.NET. A ici sunt clasele care definesc dataset -urile
Sy s t e m .D a t a .O d b c D a ta p ro v id e r .NET pentru O DBC
S y s t e m .D a t a .O l e D b D a ta p ro v id e r .NET pentru O L E DB
System.Data.Sql Clase care suport funcionalitate specific SQL
Server
S y s t e m . D a t a .O r a c l e C l i e n t D a ta p r o v id e r .NET pentru O racle
S y s t e m .D a t a .S q l C l i e n t D a ta p ro v id e r .NET pentru SQ L Server

Figura 10.1. Schema prilor componente ale arhitecturii .NET.

Interfaa cu utilizatorul

- D a t a P r o v id e r

Data Reader

Data Adapter

Command

Connection

** T.
XML v,
Baza de date :,
, f >; L v

Sarcinile pe care le ndeplinete un data provider.


Furnizeaz accesul la date printr-o conexiune activ cu sursa de date.
Asigur transmisia datelor la i dinspre cfafaset-uri (n modelul
deconectat).
Asigur transmisia datelor la i dinspre aplicaie (n modelul conectat)
C apitolul 10. B aze de d ate i A D O .N E T . N oiu n i introductive 287

C lasele unui data provider sunt:

Connection Creeaz conexiunea eu sursa de date.


Command Este utilizat pentru operaii asupra sursei de date: citire,
modificare, tergere de date.
Parameter Descrie un singur parametru al unei comenzi. De pild,
parametrul unei proceduri stocate.
DataAdapter Este un adaptor pent u transferul datelor ntre sursa de date
i dataset.
DataReader Este folosit pentru accesarea i citirea rapid a a datelor ntr-
o surs de date.

Pentru a nelege cum sunt definite n .NET aceste clase, vom lista numele acestor
clase pentru doi furnizori de date: S q l S e rve r i O LE DB .NET. Reamintim c n
spaiul de nume S ystem .D ata.S qlC lient sunt clasele furnizorului de date S q l
S erver, iar n spaiul de nume System .Data.O leD b sunt cele ale furnizorului de
date, OLE DB.
Clasele specifice celor doi data provider-'t sunt:

Furnizorul OLE DB .NET Furnizorul SQL S erver Corespunde clasei


OleDbConnection S q l C o n n e c t ion Connection
OleDbCommand SqlCommand Command
OleDbDataReader SqlDataReader DataReader
01eDbDataAdapter SqlDataAdapter DataAdapter

Pentru ca lucrurile s se lmureasc pe deplin, enumerm clasele D a t a R e a d e r


specifice tuturor furnizorilor .NET:

S y s t e m . D a t a .S q l C l i e n t .S q l D a t a R e a d e r
S y s t e m .D a t a .O l e D b .O l e D b D a t a R e a d e r
S y s t e m . D a t a . O d b c .O d b c D a t a R e a d e r
O r a c l e .O r a c l e C l i e n t .O r a c l e D a t a R e a d e r

2. Seturile de date
Dataset-ul este o component major a arhitecturii .NET. D a t a S e t este
clasa care definete un dataset. Un dataset este o colecie de obiecte D a t a T a b l e
care pot fi legate ntre ele cu obiecte de tip D a t a R e l a t i o n . Dafasef-urile preiau
de la data provider-i informaiile necesare din sursa de date sub forma unei cbpii
reduse a bazei de date. Prin urmare, un dataset poate include o baz de date
relaional cu tabele, relaii, vederi. Utilzatorul opereaz asupra tabelelor din
dataset, care sunt practic o copie a tabelelor reale din baza de date. Deoarece un
dataset este un obiect, cahe-u\ pentru datele sale este n memorie.
Dafaset-urile implementeaz modelul de lucru deconectat de baza de date.
Cnd este necesar, cfafasef-urile transmit bazei de date modificrile operate
asupra datelor.
Clasa D a taSet, ca i celelalte clase care lucreaz cu un dataset se gsesc n
spaiul de nume System .Data. Tabelul urmtor descrie aceste clase:
288 P artea a III - a. B aze de date

DataSet Obiectele sale descriu schema ntregii baze de date sau a unei
submulimi a sa. Conine tabele i relaiile ntre ele.
DataTable Obiectele reprezint o singur tabel din baza de date. Conine
rnduri i coloane.
DataRow Reprezint un singur rnd ntr-o tabel.
DataColuran Reprezint o coloan ntr-o tabel.
DataView Obiectele sorteaz datele. Nu sunt incluse ntr-un D a t a T a b l e
DataRowView Obiectele reprezint un singur rnd ntr-un DataView.
DataRelation Reprezint o relaie ntre tabele. De exemplu, o relaie de cheie
p rim a r -ch e ie strin
Constraint Descrie o constrngere n tabel, cum ar f i unicitatea valorilor ntr-o
coloan cheie primar.

Crearea unei baze de date n VCSE

Construim o baz de date n cadrul unui proiect de tip consol. Pentru


aceasta, deschidei Visual Cit Express 2008 i urmai urmtoarele indicaii:

1. Creai un nou proiect de tip consol cu numele DatabaseExample.

2. n meniul View, selectai Other Windows, apoi Database Explorer. Aceasta


este o fereastr important, n care vizualizai i manipulai elementele bazei
de date pe care o vei crea.

3. n Solution Explorer, acionai click drept pe numele proiectului, alegei Add,


apoi New Item ... n dialogul A dd New Item, selectai iconu! Service-based
Database, apoi numii baza de date coala,

Twnptatss:

V isu al S tu d io in s t a lle d t e m p la t e s

cO
ip
About Sox Appcaon Application Assembly Class Code Fe DataSet Debugger
Configurai... ManifestFe Informai... Visua2 r

i ti m
Interface U N Q to 5QL local MOI Parent Resources Fe Settings Fe Text Fe
Classes Database Form

i u
User Control User Control Windows Form XM l Fe
(WPF)
An empty SQ L Server database for service-based data access

Mame: : Scoala.mdf
C apitolul 10. B aze de date i A D O .N E T . N o iu n i introductive 289

Remarcai c exist i alternativa de a alege Local Database. In aceast


situaie, baza de date este creat de ctre SQL S e rve r C o m p a c t E d itio n . Are
extensia .sdf, i este destinat s fie utilizat local. Testai i aceast variant.

4. n panoul A dd New Hem. acionai butonul Add. Dialogul Data Source


Configuration Wizard v anun c va construi un dataset vid, pe care l putei
configura ulterior. Acceptai numele S c o a l a D a t a S e t pentru acesta:

Data; Source Configuration Wizard > '-S.**.

Choose Your Database Objects

Which database objects do you want in your dataset?

! The database you selected is new or does not contain any objects. Click Finish to create an empty dataset. ;
: Once database objects are added to the database open th e empty dataset in the Dataset Designer to j
i reconfigure the dataset. j

DataSet name:

< Previous Finish Cancel

Apsai butonul Finish.

n panoul D atabase E xplorer, expandai nodul Scoala.mdf, care reprezint


baza de date. Click dreapta pe Tables, i selectai A dd N ew Table:

{WtatJ&e Explorer B Q

; c \ j i Data Connections
i 3 U j Scoala.mcff
* C il Database Diagrams
a pEES
| -t Views !, . AcfdMewTaWe
| + C il S to re d
Mew Query
* 1 Funciei
ti _1 Synoni 2 ] Refresh
; * CCi Types
Properties
ZA Asseml ' a
290 P artea a III - a. B aze de date

6. Panoul care se deschide este Table D esigner. Acesta v permite s definii


schema tabelei, adic numele, tipul i constrngerile pentru fiecare coloan.
Completai prima linie ca n figur. n fereastra Column Properties, setai
pentru cmpul IdElev, proprietatea I s l d e n t i t y la valoarea Yes i Identity
Increment ta valoarea 1. Aceasta nseamn c tipul coloanei trebuie s fie int,
iar valorile pe coloan se incrementeaz n mod automat ncepnd de la
valoarea 1, pentru fiecare rnd nou introdus. n acest fel, Id E le v poate
identifica n mod unic un rnd n tabel:

Database Explorer. : t ' ? x ] dbo.Tablel: T...E\SCOALA.MDF)* Program.cs


Column Name Data Type Allow Nulls
3 j l Data Connections
I B IdElev Int
3 Ob Scoala.mdf
ffl u il Database Diagrams

IB Tables
Si Views
S C3 Stored Procedures Column Properties
ill Functions
Si C3 Synonyms m i
ffl Types
3 H I Assemblies |B. Full-text Specification No

:I3 Identity Specification Yes


I, (Is Identity) Yes
i
Identity Seed 1

7. Vom stabili pentru coloana IdElev, o constrngere de cheie p rim a r (primary


key). Facem acest lucru pentru a vedea cum se procedeaz i nu pentru c ar
fi necesar, deoarece ID EIev este deja o coloan Id e n tity. Deseiectai check
6ox-ul A llow Nulls, deoarece o coloan Identity sau o cheie primar nu admite
valori nule. Selectai n Table Designer primul rnd, facei click dreapta i
alegei Set Prim ary Key.

I Column Name Data Type Allow Nulls


|T T id E le v ;:^ : ^ ;:.
I | Set Primary Key

: Insert Column

: Delete Column

Relationships..,

8. Definii celelalte coloane astfel:


C apitolul 10. B a ze de date i A D O .N E T . N o iu n i introductive 291

.J-
'1 Column Name Data Type Allow Nulls
ll IdElev int
ii Nume nvarchar(30)
|j Prenume nvarchar(30) 0
j ! W Versta 33 -V."1 0
-i ':1' -
i ' nt Ea
i " " money
1:
! il nchar(lO)

9. Salvai proiectul i tabela apsnd butonul Save AII. n dialogul Choose Narne
introducei numele tabelei: Elevi.

10. Pentru a nsera (design time) cteva rnduri cu date n tabel, expandai
nodul Tables n D atabase E xplorer. Click dreapta pe tabela E l e v i i
selectai Show Table Data.

d b o -E le v i Ta_LE\SCO ALAJdDF) a a rt Page

Column Name ^D ata Type


a | j j Data Connections : IdElev ! irit
S L t Scodia.mdf Nume n v a rc h a r(3 0 )
3 Database Diagrams
Prenume nvarchar(3C)
^ li Tables
s m a r nt
Add N ew Table

3 N Add N ew Trigger

N ew Q u ery
. ^
O pen Table Definition
_i Views j
ic ZI Stored Pr S h o w T ab le D a ta
PuTW+ivVid c

11. S-a deschis Query Designer. AiPi putei introduce manual date n tabel i
putei efectua interogri. Completai cteva rnduri, ca mai jos. Observai c pe
coloana i d E l e v serverul nu v permite s introducei valori, deoarece este
coloan Id e n tity i aceasta nseamn c SQL S erver ii atribuie valori n mod
automat:

m * IM ' [S * 3 _. : ^ ^ _3.
Elevi: Q uery(...L E\SC O L A .M D F) d b a fle v i: J ^ X ^ C O A t A ^

'I j IdElev Nume Prenume Versta

Pascu loan 18
9 Nedelcu Valentin 17

3 Pop Andrei 19

4 Ilie loan 18
* i NULL NULL NULL
292 P artea a III - a. B aze de date

12. Dac dorii s adugai i alte tabele bazei de date coala, de pild tabelele
Clase, Pr o f e s o r i , M a t erii, e foarte simplu: facei click dreapta pe Tables
n Database E x p lo re r i alegei New Table., apoi repetai paii 6...11.

Nu vei face b u ild acestui proiect, pentru c aplicaia nu execut nimic. Vom vedea
n seciunile urmtoare cum ne conectm la baza de date i cum o interogm
programatic.

De reinut:

O cheie prim ar (p rim a ry key) identific n mod unic fiecare rnd ntr-o
tabel. Cheia primar include o coloan sau o combinaie de coloane. Nu
pot exista dou rnduri distincte ntr-o tabel care s aib aceeai valoare
(sau combinaie de valori) n aceste coloane.
O co lo a n id e n tita te (Id e n tity colum n) identific n mod unic fiecare rnd
ntr-o tabel, iar valorile sale sunt generate de ctre baza de date. Deseori
o coloan identitate e desemnat i cheie primar.
v a r c h a r (n ) este un tip de dat specific SGDB-urilor, care reine un set
de caractere de lungime variabil, dar care nu depete n. Pentru SQL
Server 2005, n poate fi maxim 8000 bytes.

Interogri cu Query Designer

n aceast seciune vom face cteva exerciii de manipulare a datelor, n


scopul mprosptrii cunotinelor referitoare la comenzile limbajului SQL. Utilizm
baza de date coala, construit anterior.
Deschidei proiectul DatabaseExample. n D atabase E xp lo re r, acionai
click dreapta pe T ables i alegei New Query. n dialogul A dd Table selectai tabela
E l e v i i acionai butonul Add. Se deschide Query Designer-ul mediului integrat,
care vizual consist din patru panouri: Panoul Diagramelor (Diagram Pane),
Panoul Criteriilor {Criteria Pane), Panoul SQL (SQL Pane), Panoul de Vizualizare
a Rezulatelor ( Show Results Pane).
n Panoul SQL vom introduce interogri, iar rezultatele interogrii, adic
setul de rezultate, este vizualizat n Panoul Rezultatelor. Panoul diagramelor
permite selectarea coloanelor iar cel al criteriilor servete la stabilirea criteriilor de
sortare. Toate seleciile fcute n cele dou panouri genereaz cod n Panoul SQL.
Reamintim faptul c limbaljul SQL (Structured Query Language) include
dou seciuni importante:

1. Data M an ip u la tio n Language (DML).


D M L const din interogri i comenzi pentru modificarea datelor.
Acestea sunt: s e l e c t ,u p d a t e ,d e l e t e i i n s e r t i n t o .

2. Data D e fin itio n Language (DDL).


Comenzile DDL permit crearea i tergerea tabelelor ntr-o baz de
date. Cele mai importante comenzi de acest tip sunt: c r e a t e TABLE,
A L T E R TABLE, D R O P TABLE.
C apitolul 10. B a ze de date i A D O .N E T . N o iu n i introductive 293

Butoanele
panourilor

m .s S = ! 3
Q u e ry 4: Q uery...E \S C O A LA .M D F) start Page

(All Columns)
plldE lev Diagram
0N um e
b/j Prenume
0 Varsta

I . Column Alias Table


i
I Nume Elevi
Criteria Pane
i Prenume Elevi
I Varsta Elevi

;ISELECT Nume, Prenume, Varsta SOL Pane


FROM Elevi

Show Result
Pane

Figura 10.2 Query Designer

Executarea in te ro g rii
Pentru executare acionai click pe butonul Execute SQL (butonul cu semnul
exclamrii) sau de la tastatur Ctrl + R.
n panoul de rezultate, se afieaz:

! Nume Prenume Varsta


j Pascu loan L8
j Nedelcu Valentin L7
iPop Andrei L9
Ilie loan 18
294 P artea a III - a. B aze de date

Comanda SELECT
SELECT este utilizat pentru selecatrea datelor dintr-o tabel. Rezultatul
este retumat ntr-o form tabelar, numit result set.

Sintax:

SELECT nume coloane FROM tabela

E xem plu:
Introducei n SQL Pane comanda urmtoare, dup care o executai cu un
click pe butonul Execute SQL:

S ELECT Nume, Prenume, Varsta FROM Elevi

Putei face acest lucru manual, sau bifai n Diagram Pane coloanele
corespunztoare.

Sortare
Ca s introducei criterii de sortare n comanda SELECT, utilizai Panoul
Criteriilor (selectai o opiune din coloana Sort Type) sau le introducei manual.

Exemplu:
Introducei n SQL Pane comanda:

SELECT Nume, Prenume FROM Elevi


ORDER BY Nume

Rezultat:

Nume Prenume
Ilie loan
Nedelcu Valentin
Pascu loan
Pop Andrei

Clauza W HERE

WHERE permite selecia condiionat. Cu * selectai toate coloanele tabelei.

E xem plu:
Introducei n SQL Pane comanda:

SELECT * FROM Elevi


W H E R E V a r s t a > = 18
C apitolul 10. B aze de date i A D O .N E T . N o iu n i introductive 295

Rezultat:

IdElev Nume Prenume Varsta


1 Pascu lean 18
3 Pop Andrei 19
4 Ilie lean 18

Comanda INSERT INTO


Comanda insereaz un rnd nou n tabel.

Sintax:

I N S E R T I N T O nume_tabel
V A L U E S valoarel, valoare2, ...

: Putei de asemenea s specificai coloanele n care se nsereaz date:

v I N S E R T I N T O nume_tabel [coloanal, coloana2, ...)


V A L U E S valoarel, valoare2, ...

Exemplu:
; Introducei n SQL Pane:
i
INSERT INTO Elevi (Nume, P r e n u m e , V a r s t a )
V A L U E S ('Florea', ' C o n s t a n t i n ' , 99)

Rezultat:
jj Pentru a vedea rezultatul, avem nevoie de un result set ntors de o
d instruciune s e l e c t . Introducei interogarea:

j SELECT * FROM Elevi


] | ______________________________________________________
; IdElev Nume Prerume Va

11 Pascu loan 18

I2 Nedelcu Valentin 17

h Pop Andrei 19
j4 Ilie loan 18

{7 Florea Constantin 99

Comanda UPDATE
Comanda este utilizat pentru modificarea datelor ntr-o tabel.
296 P artea a III - a. B aze de date

Sintax:

UPDATE nume_tabel
SET c o l o a n l = v a l o a r e l , coloan2 = v a lo a re 2 , ...
WHERE coloan = v a lo a re

Cu u p d a t e putei modifica valorile pe una sau mai multe coloane, n rndurile


selectate cu clauza w h e r e .

E x e m p lu :
Introducei n SQL Pane:

UPDATE Elevi
S E T V a r s t a = 104
W H E R E P r e n u m e = 'loan'

R e z u lta t:
Pentru a vizualiza rezultatul introducei n SQL Pane interogarea:

SELECT * FROM Elevi

IdElev Nume Prenume Varsta


1 Pascu loan 104
2 Nedelcu Valentin 17

3 Pop Andrei 19
4 Ilie loan 104
2 Florea Constantin 99

Comanda DELETE
Comanda este utilizat pentru tergerea rndurilor dintr-o tabel.

Sintax:

DELETE FROM nume_tabel


WHERE co loan = v a lo a re

E x e m p lu :
Introducei n SQL Pane comanda urmtoare, dup care executai-o cu click
pe butonul Execute SQL:

DELETE FROM Elevi


WHERE Varsta > 1 9

R e z u lta t:
Pentru a vizualiza rezultatul introducei n SQL Pane interogarea:
C apitolul 10. B a ze de date i A D O .N E T . N o iu n i introductive 297

SELECT * FROM Elevi

j IdElev Nume Pr anume Varsta

2 Nedelcu V aentin 17

|:3 Pop A ra x i 19

Comanda CREATE TABLE


Comanda creeaz o tabel ntr-o baz de date.

Sintax:

CREATE TABLE nume_tabel


(
coloanal tip_dat,
coloana2 tip_dat,

E xem plu:
Lucrm cu aceeai baz de date, coala. Introducei n SQL Pane
comanda urmtoare, dup care executai cu un click pe butonul Execute SQL:

CREATE TABLE Clase (IDClasa varchar(5), Profil varchar(20),


N r E l e v i int)
Rezultat:
n Database E x p lo re r a aprut tabela Clase. Acionai click drept asupra
numelui clasei i selectai Open Table D e fin ito n :

Column Name D ata Type Allow Nulls


IDClasa varchar(5) 0 '
I Profil varchar(20) 0
NrElevi int 0

Comanda ALTER TABLE


Comanda este utilizat pentru a aduga sau a terge coloane ntr-o tabel.

Sintax:

ALTER TABLE tabel


ADD c o lo a n tip

ALTER TABLE tabel


DROP COLUMN coloan
298 Partea a III - a. B aze de date

Exemplu:
Introducei n SQL Pane comanda urmtoare, dup care o executai cu un
click pe butonul Execute SQL:

ALTER TABLE Clase


ADD Diriginte varchar(20)

Rezultat:
n Database Explorer acionai click drept asupra numelui clasei i selectai
Open Table Definition:

;j Column Name Data Type Allow NuIIs


m IDCiasa varchar(5) 0
|j Profil varchar(20) 0
ii NrElevi int 0
j y | Diriginte . j varchar(2Q) 0

Exemplu:
Introducei n SQL Pane comanda pentru tergerea coloanei D i r i g i n t e :

A L T E R T A B L E Clase
D R O P C O L U M N Diriginte

Rezultat:

Column Name Data Type Allow Nulls


IDCiasa varchar(5) 0
Profil varchar(20) 0
NrElevi int 0

Comanda DROP TABLE


Comanda este utilizat pentru a terge o tabel ntr-o baz de date.

Sintax:

DROP TABLE tabel

Exemplu:
Vom terge tabela Clase. Introducei n SQL Pane comanda urmtoare,
dup care o executai cu un click pe butonul Execute SQL:

DROP TABLE Clase

Rezultat:
C apitolul 10. B aze de date i A D O .N E T . N o iu n i introductive 299

n Database Explorer, click dreapta pe T ables i selectai Refresh. Se


observ c tabela c la s e a fost tears.

Controlul DataGridView

Acest control este vedeta controaelor pentru afiarea datelor. Clasa


D a taGridView permite construirea unei "abele adaptabile. Celulele, rndurile,
coloanele se seteaz prin intermediul proprietilor Rows i Columns.
Controlul se poate popula manual sau programatic. Ca alternativ, controlul
se poate lega" la o surs de date prin intermediul proprietilor DataS o u r c e i
DataMember. Astfel popularea se face n mod automat.
Prezentm un exemplu de manipulare simpl a acestui control.

Aplicaia DataGridViewExample
Realizm un proiect de tip consol, cate conine o baz de date cu o singur
tabel. Informaiile din tabel se vor afia ntr-un control D ataG ridV iew n
momentul pornirii aplicaiei. Urmai paii:

1. Creai un proiect de tip Windows Forms cu numele DataGridViewExample.

2. Construii o baz de date cu numele S port. Adugai n baza de date tabela


Sportivi. Tabela are urmtoarea structur:

Column Name Data Type . Allow Nulls


| IdSportiv V:'.;'"] int | |
Nume nvarchar(15) Q
Prenume nvarchar(lS) [v ]
DataNasterii datetime 0
SportulPracticat nvarchar(30) Q

Pentru construirea bazei de date i a tabelei, urmai indicaiile temei: Crearea


unei baze de date n VCSE.

3. Introducei cteva nregistrri n tabel. Pentru aceasta, selectai tabela


Sportivi n Database E xplorer, acbnai click dreapta i alegei Show
Table Data.

4. Din T o o lb o x, tragei pe suprafaa formei un control de tip D ataG ridV iew i


setai proprietatea D ock la valoarea F i i i .

5. Selectai controlul. n fereastra P roperties, atribuii proprietii DataS o u r c e


valoarea Sportivi. Se face acest lu c rj, expandnd n panoul din dreapta
n mod succesiv nodurile: Other Data Sources, Project Data Sources i
SportDataSet:
300 P artea a III - a. Baze de date

IlM illL :
Cursor Default
DataMember
I(none)
Defau
* m r
Dock 3 {J J Other Data Sources
EditMc 9 ( S Project Data Sources
Enable 3 \|] SportDataSet
Enable 3 Sportivi
Gener, S - 2 1 Forml List Instances

GridCd

Astfel, n mod vizual, ai legat controlul la sursa de date.

6. Facei B u ild i rulai cu F5.

La rulare obinei:

: IdSportiv : Nume Prenume DataNasterii SportulPracticat

1 8 Dita Tomescu Constantina : 23.01.1970 : Atletism - '.

Izbasa Sandra i 28.05.199S 1Gimnastica $


I
|3 Dumitru : Alina ; 30.08.1982 ; Judo

i Andrunache ; G eorgeta ! 14.04.1376 i Canotaj

]5 ISusanu ; Viorica 129.10.1975 ! Canotaj *


< :

Exist i ate variante vizuale pentru popularea controlului.

V arianta a 2-a
Procedai dup cum urmeaz:
Paii 1, 2, 3, 4 sunt identici cu cei specificai anterior. Continuai astfel:

5. In meniul Data, selectai Show Data Sources. n fereastra Data Sources,


acionai click dreapta pe elementul S p o rtD a ta S e t, apoi selectai Configure
DataSet with Wizard...

Start I

SportDataSet
j rjj Add New Data Source...

j jjj Edit DataSet with Designer

I Configure DataSet with Wizard...


C apitolul 10. B a ze de date i A D O .N E T. N o iu n i in trodu ctive 301

6. n dialogul Data Source Configuration Wizard, selectai tabela Sportivi, apoi


apsai butonul Finish:

Choose Your Database Objects

Which database objects do you want in your dataset?

| bi 0 ' - ^ Tables
i 0 ZD Sportivi
i 0 1 ^ 3 Views
| 0 U rjJ Stored Procedures

In fereastra Data Source, selectai tabela Sportivi i tragei-o pur i simplu


cu mouse-ul deasupra controlului D ataG idView, n Form Designer.

'Data Sources SportDataSet.xsd StarlPage ; r o m i . * f o r m lx [Design]* Sprtlvi: Que


j j Pj -t*
2 *} 5>ortOaUSt
cri v J SOfOvi v
w IdSportiv
-*W Nume
*w. Ptenume
7? D-tfaN-ssCrr
SportuPr<*:tiea'

8. Facei B u ild i rulai cu F5. Vei obine popularea controlului cu datele din
tabel.

V arianta a 3-a
Procedai astfel:
Paii 1, 2, 3, 4 sunt identici cu cei ai aplicaiei anterioare. Continuai astfel:

5. Deschidei D ataS et D esigner. Pentru aceasta, avei dou posibiliti: n


S o lu tio n E x p lo re r facei dublu click pe itemul S p o r t D a t a S e t .x s d sau n
panoul Data Source, click dreapta pe itemul S p o r t D a t a S e t i selectai E dit
DataSet with Designer.

: ij Add New Data S o u r c .,.

I EcS* DataSet wrth Degner


302 P artea a III - a. B aze de date

6. n D atabase E xp lo re r, selectai tabela Sportivi i o tragei cu mouse-ul pe


suprafaa D ataS et D e sig n e r-ului:

p o r rta e U ttd *; 'a ^ p g e !


iir

i B i j | J D a t a C o n n e c tio n s i Sportivi . B M Ia l
B 0t Sport.mdf
IdSportiv
B Q | Database Diagrams
3 GJ Tabtes Nume

S 5 3 Sportivi Prenume
33 IdSportiv DataNasterii
3] Nume Sportufracticat
T] Prenume
53 DataNasterii
lai Fi.GetData ()
,53 SportuIPracticat ;l
ffi G 2 Views I!

7. Deschidei F o rm D e sig n e r-ul cu dublu click pe Forml.cs n S o lu tio n


E xp lo re r. n panoul Data Source, selectai cu click tabela Sportivi i
plasai-o pe suprafaa controlului DataGridView.

8. Facei b u ild i rulai cu F5.

Observaii:
> Toate cele trei variante de populare a controlului D ataG ridV iew realizeaz o
le g a re a controlului la sursa de date printr-un obiect de tip BindingSource.
> Despre clasele DataSet, BindingSource, Table Adapter, dar i despre
modul n care populai programatic un control D ataG ridV iew , vom discuta n
seciunile urmtoare.

Configurarea design time a coloanelor unui DataGridView


Coloanele se adaug i se configureaz astfel:

1. n Form D esiger acionai click pe sgeata din colul dreapta sus al controlului
D ataG ridV iew , apoi alegei Edit Columns.

2. n dialogul Edit Columns adugai coloane. Pentru fiecare coloan avei n


panoul U nbound Column Properties, diverse proprieti care pot fi setate, ntre
care i textele header-elor.
C apitolul 10. B aze de d ate i A D O .N E T. N o iu n i introductive 303

_sr DeUGrtdVte* Tasks


IDSportrv Sport Practicei- ~
Choose Data Source (none)

Ed* Columns...
Edit Columns
:
Add Column...

Selected Cofcjnns: Unbound Column Proi*bes 0 Enable Addtig

^ ig m s ______ 3 Enable Edbnq


; Nume
K a xlrp o tle n o th 327S7
;.*' Prenume ;s 3 Enable Deleting
!. Readonly False
Data Nested Enable Column Reordering
}' Resizable True
. bv Sport Practicat * SortMode Automatic Dock in pat ent container
:Q D e ta : '_'t *"v ;
OataPropertyNacw (none)
Design ...
(Name) " .V C o im n l
f; CdumnType DateGridVtewTexcSoxColu.vjl

: (Name)
. Indfcates the nane uswi in code to identify the
; object.

I c* !
304 Partea a III - a. B aze de date

Capitolul 11

Aplicaii cu baze de date n modelul conectat


ADO.NET permite aplicaiilor s lucreze att n m o d e lu l c o n e c ta t ia baza
de date, ct i n m o d e lu l deconectat.
n modelul conectat se utilizeaz provider-ii specifici diferitor surse de date.
De exemplu, pentru comunicarea cu SQL S erver 2005, folosim clasele specifice
acestui provider: SqlConnection i SqlReader. Aplicaia se conecteaz,
execut interogrile, apoi se deconecteaz.
n modelul deconectat se creaz un dataset care preia din baza de date
tablele necesare. Aplicaia se deconecteaz de la baza de date, execut interogri
asupra acestui dataset, apoi face update-ul necesar n baza de date.
n continuare propunem cteva modele de lucru cu bazele de date, att n modelul
conectat ct i deconectat. Vor fi aplicaii de tip consol, dar i de tip Windows
Forms.
Vom realiza cteva aplicaii care folosesc provider-ul pentru SQL S e rve r 2005,
pentru OLE DB i pentru ODBC. Reamintii-v c ADO.NET include data provideri
pentru diferite surse de date.

Utilizarea p ro v id er-u iu i pentru SQL S e rv e r 2005

Realizm o aplicaie este de tip consol. Relum aplicaia DatabaseExample


din capitolul anterior. Aceasta conine baza de date coala, cu o singur tabel;
Elevi. S presupunem c tabela are doar dou rnduri;

! IdElev Nume Prenume Varsta

11 Nedelcu Valentin 17

1.2 Pop Andrei 19

Executm dou operaii asupra tabelei E le v : inserarea unui rnd nou i selectarea
rndurilor.

Urmai paii:

1. Deschidei aplicaia de tip consol, DatabaseExample. n S o lu tio n E xplorer,


redenumii Program, cs astfel: SQLDataProvider.es (ciick dreapta i
Rename).

2. Deschidei fiierul SQLDataProvider.es (click dreapta i View Code) apoi


nlocuii codul existent cu urmtorul:

u si n g System;
using System.Data.SqlClient;
C apitolul 11. A p lica ii cu baze d e date n m o d elu l con ectat 305

namespace ConsoleAoplicationl
{
class SQLDataProvider
{
static voicl Main (string [] args)
1
// Construim stringul de conectare
// (cozmectioa string)
string connString =
server = .\sqlexpress;
Database=Scoa.la.mdf ;
trusted_connection=True;
AttachDbFileName =
C :\DatabaseExample\DatabaseExample\bin\Debug\Scoala.m d f " ;

// Pregtim interogrile
string sqll = @"SELECT * FROM Elevi";
string sql2 = 0"INSERT INTO Elevi
(Nume, Prenume, Varsta)
VALOES
('Axente', 'Mihai', 20)";

// Declarm variabilele conexiune


// i cititorul de date
SqlConnection conn = n u l i ;
SqlDataReader reader = n u l i ;
try
{
// Deschidem conexiunea
conn = new SqlConnection(connString);
conn.Open();

// Executm prima interogare


SqlCommand cmd = new SqlCommand(sqll, c o n n ) ;
reader = cmd.ExecuteReader();

// nchidem reader-ul
II pentru a putea fi refolosit
reader.Close ();

I/ Executm a doua interogare - inserarea


// unui rand
cmd = new SqlCommand(sql2, c o n n ) ;
reader = c m d .ExecuteReader();
reader.Close();

// Din nou un SELECT pentru a avea


// un result set
cmd = new SqlCommand(sqll, conn);
306 P artea a III - a. B aze de date

reader = c m d .ExecuteReader();

Console.WriteLine("Baza de date " +


conn.Database + " se interogheaz cu "
+ cmd.CommandText);

// Afim informaiile din result set


while (reader.Read())
Console.WriteLine("{0} {1} (2}",
reader[l], r eader["Prenume],
re a d e r [3]);
Console.WriteLine();
}
catch (Exception e)
{
Console.WriteLine("Eroare: " + e ) ;
}
finally
{
// Conexiunea se nchide indiferent dac se
// arunc sau nu excepii
r eader.C l o s e ();
conn.Close();
conn.Dispose();
}
} / / M a i n ()
}
}

3. Facei B u ild i rulai cu Ctrl + F5 (Modul depanare)

_iJ

Reinei etapele comunicrii cu baza de date:

Paii urmtori sunt aceeai indiferent de providerul cu care lucrai:

Se include spaiul de nume S ys t e m . D a t a .SqlClient.


Clasele acestuia definesc providerul pentru MS SQL Server. Pentru ali
provideri, se nlocuiete prefixul Sql cu cei corespunztor.

Se deschide o conexiune cu baza de date


C apitolul 11. A p lic a ii cu baze de date n m o d elu l con ectat 307

> Clasa SqlConnection pernie obinerea unei conexiuni la server


i deschiderea conexiunii cu metoda O p e n ().
> Constructorul acestei clase, SqlCon n e c t i o n (connString),
primete stringul de conectare.
> Proprietile Database i CommandText ale clasei
S q l Connection retumeaz baza de date, respectiv interogarea
curent.

Executarea interogrii

> Ca s executai o interoga, trebuie mai nti s construii un


obiect de tip SqlCommand.
> Constructorul SqlCommand(sql,conn) primete ca argumente
interogarea care trebuie executat i conexiunea prin care va
lucra.
> Executararea propriuzis a interogrii, se face cu metoda
E x e c u t e R e a d e r (). Aceasta face dou lu cru ri: construiete un
obiect (reader) de tip SqlData R e a d e r i apoi execut
interogarea.
> Metoda ExecuteReader () retum eaz un result set care poate fi
vid pentru comenzi non-query, cum este i n s e r t i n t o , dar nevid
pentru SELECT. Acest result set se poate imagina ca o tabel n
care se regsesc rezultatele nterogrii.

Accesarea rezultatelor interogrii

> Ca s analizai setul de rezultate, parcurgei setul n bucl cu


metoda R e a d ) , care la fiecare apel, avanseaz re a d e r-u ! la
urmtoarea linie.
> Datele de pe linie se acceseaz indexat, r e a d e r [0 ] este
valoarea corespunztoare primei coloane, reader [l ]
corespunde celei de a doua coloane, etc. Un alt mod de accesare
este prin numele coloanei respective, aa cum am artat n
aplicaie: reader ["Prenume"] este valoarea aflat pe linia
curent i coloana Prenume. Se prefer accesarea prin indeci
pentru c este mai rapid.

Protecia mpotriva excepiilor


> Deschiderea conexiunii (nev S q l Connection (connString) )
trebuie protejat ntr-un bloc try ...catch. pentru tratarea
excepiilor. Astfel ne asiguim c blocul finally, n care
eliberm resursele va fi executat. Se face acest lucru, deoarece
ADO .NET arunc excepii la erorile de baze de date. Este foarte
simplu s avei erori. De exemplu, greii ceva n stringul de
conectare, sau baza de date este blocat de cte o alt aplicaie.
308 P artea a III - a. B aze de date

Blocul u s in g - o tehnic sigur

Clasele Connection, aa cum este SqlConnection motenesc interfaa


iDispos&ble. Aceasta nseamn c un obiect de acest tip poate referi resurse
negestionate n mod automat de .N E T (unmanaged resources). Poate fi vorba de
surse de date, fiiere pe disc i altele. Toate clasele care motenesc aceast
interfa au metoda DisposeO, care trebuie invocat de ctre programator
pentru eliberarea acestor resurse. In mod obinuit, se apeleaz n blocul f inally.
O metod mai elegant pentru tratarea excepiilor este utilizarea blocului
using. Nu confundai cu directiva using. Obiectele iDispozable se declar i
se instaniaz n declaraia using. n acest fel, v asigurai c metoda Dispose ()
este apelat chiar n cazul n care se arunc excepii.
lat cum se poate scrie codul cuprins n blocul t r y ... c a tc h n programul
de mai sus:

using (conn = new SqlConnection(connString) )


{
c o n n .O p e n ();

SqlCommand cmd = new SqlCommand(sqll, conn);


reader = cmd.ExecuteReader();

// cod ...

while (reader.R e a d ())


Console.WriteLine("(0) {1} {2}",
reader[l], r eader["Prenume"],
r eader[3]);
reader.Close () ;
}

Observai c nu mai este nevoie nici mcar s nchidei conexiunea,


deoarece de acest lucru se ocup acum C#.

Ce reprezint connection string ?

Stringui de conectare este un string care specific informaii despre o surs


de date, precum i mijloacele de conectare la aceasta. Se transmite data provider-
ului pentru iniierea conexiunii. Conine atribute cum s u n t: numeie driverului,
numele serverului de baze de date, numele bazei de date, informaii de securitate
cum ar fi user i parol i altele.
n aplicaia anterioar, server = .\sqlexpress; specific faptul c se
utilizeaz o instan a SQL Server 2005 Express Edition, aflat pe maina local
(prin . \ se precizeaz c e vorba de localhost).
Se indic deasemenea numele bazei de date prin Database=Scoala .mdf; Mai
departe, trusted_connection=True; permite userului curent autentificat s
fac o conexiune.
C apitolul 11. A p lic a ii cu baze de date n m o d elu l con ectat 309

Atributul AttachDbFileNaiae specific calea de director pe discul local pn la


baza de date. Procesul prin care aducei lai cunotin serverului SQL S e rve r de
existena unei baze de date se numete ataarea bazei de date.
Ajuni n acest punct, precizm c baza de date se compune din dou
fiiere strns legate : fiierul cu extensia (,mdf) i cel cu extensia (.Idf). Primul
depoziteaz datele, iar al doilea este fiier de lo g , care conine informaii despre
tranzacii.
Exist mai multe atribute care pot fi incluse n stringul de conectare. De
multe ori, alegerea lor corect este o problem. Din fericire, exist destul
documentaie i chiar site-uri dedicate. Recomandm unul dintre acestea:
w w w .c o n n e c tio n s trin g s .c o m .

U tilizarea p ro v id e r-u lu i p e n tru O L E D B

Cu ajutorul furnizorului de date OLE DB, se pot accesa date depozitate n


diverse tipuri de baze de date, de la MS A c c e s s pn la O racle. V putei conecta
inclusiv la SQL S erver 2005, ns acesta are propriul lui provider, aa cum ai
vzut, care este mai rapid. Acest data provider este definit n spaiul de nume
System .Data.O leD b. Cele mai importante clase ale sale sunt:

OleDb C o m m a n d Execut interogri sau proceduri stocate


O l e D b Connection Reprezint o conexiune ia o surs de date
OleDbDa t a R e a d e r Pennite citirea numai nainte, a unui stream de rnduri
dintr-o surs de date
OleDbDataAdaptor Reprezint o legtur ntre sursa de date i dataset,
folosit pentru obinerea i salvarea datelor.

Este uor de remarcat similitudinea ntre clasele furnizorului OLE DB i cele ale
SQL S erver 2005. Metodele acestor clase sunt de asemenea similare.

Aplicaia OleDbProviderWinApp

Vom accesa o baz de date Microsoft Access 2003 cu ajutorul providerului


Microsoft. Jet.OLEDB. 4 .0. Acest furnizor este specific pentru bazele de date
Access.
Urmai procedura:

1. Deschidei Micosoft Access i creai baza de date Access P ersoane.m db, cu


urmtoarea schem:
310 P artea a III - a. Baze de date

E3MicrosoftAccess
: Eiier d ta r e V g u a b a re ' In se ra re In strj/n e n te

; ft Persoane :* Tabel
Nume cmp I Tip de date I
9 ID AutoNumerotre
Nume Text
Prenume Text
DataNasteni Dat/Or

Completai cteva rnduri cu date n tabel. Salvai baza de date


P ersoane.m db n folderul C :\teste.

2. Creai n VCSE un nou proiect de tip Windows Forms, cu numele


OleDbProviderWinApp.

3. Pe suprafaa formei plasai un control de tip DataG ridView .

4. n fiierul Form1.es introducei directiva: using System.Data.OleDb;

5. Intenionm s populm controlul la ncrcarea formei. Prin urmare, tratm


evenimentul Load pentru form. Acionai dublu click pe suprafaa formei. n
corpul handter-u\u\, introducei codul marcat cu Bold:

private void Forml_Load(object sender, EventArgs e)


{
// Setm numrul coloanelor i textul header-eloz
dataGridViewl.ColumnCount = 4;
dataGridViewl.Col u m n s [0].HeaderText = "ID-ul";
dataGridViewl.Columns[1].HeaderText = "Numele";
dataGridViewl.Columns[2].HeaderText = "Prenumele";
dataGridViewl.Columns[3].HeaderText = "Data Naterii";

// Stringul de conectare
string connString =
@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=
C :\teste\Persoane.mdb;";

// Stringul de interogare
string sql = @"select * from Persoane";

// Declarm variabilele conexiune i data reader


OleDbConnection conn = nul i ;
OleDbDataReader reader = nuli;

// Crem conexiunea
using (conn = new OleDbConnection(connString))
{
Capitolul 11. A p lic a ii cu baze de d a te n m odelu l conectat 311

conn.Open(); // Deschidem conexiunea

// Se execut interogarea
OleDbCommand cnd = new OleDbCommand(sql, conn);
reader = cmd.ExecuteReader();

// Tablou de stringuri. Reine valorile unui rnd


// din tabel
string[] r = nuli;
// Metoda Read() avanseaz reader la un rnd nou
while ( reader.R e a d () \
{
r = new string[4][ r eader[0].ToString(),
reader[1].ToSt r i n g (),
reader[2] .ToStringO ,
reader[3].ToString() };
// Adugm rndul in control
dataGridViewl.R o w 3 .Add(r);
}
reader.Close();
} // using
1

6. Compilai i executai cu F5.

Vei avea ceva asemntor:

iID'ui Numele Pienumele Data Naterii


voicu ;Ionel i16.01.198800:0...
j2 ;Grapini Grigore i10.11.138700:0...
(3 jPop !loan i21.02.199000:0...
\A !uliniei ISorin i14.07.199100:0...
* j |
< >

De rein
> ut:

> Coloanele, mpreun cu textul header-elor se pot aduga design time, ns


am dorit s artm cum le setai programatic.
> Stringul de conectare are dou atribute: Provider i Data Source.
Primul indic providerul OLE DB pentru bazele de date A ccess, iar al
doilea indic sursa de date i locaia sa.
312 P artea a III - a. B aze de date

> Rndurile se adaug n control cu metoda A dd ( ) :


d a t a G r id V ie w l. Rows . A dd ( r ) ; , unde r este un ir de stringuri care
reine valorile reader-u\ui.
> Declaraia u s i n g asigur eliberarea resurselor alocate att pentru o ieire
normal din bloc, ct i la aruncarea unei excepii. Observai c nu este
nevoie s mai nchidei conexiunea, ci doar reacfer-ul.
> Remarcm similitudinea codului i a tipurilor utilizate pentru provider-u
S Q LS erver i OLE DB.

U tilizarea p ro v id e r-u iu i p e n tru O D B C

ADO.NET include furnizorul de date ODBC n spaiul de nume


S ystem .Data.O dbc. Este prima tehnologie Microsoft de accesare a surselor de
date, fiind nc folosit pentru surse de date care nu au provider OLE DB. Poate fi
folosit cu aproape oricare tip de surs de date. ODBC comunic cu sursa de date
prin intermediul driver-ului sursei de date, deci apare un nivel intermediar i
aceasta face ca viteza de lucru s fie mai mic n raport cu ali provideri.
Cele mai importante clase asociate provider-ului ODBC sunt uor de
recunoscut, dup prefixul O dbc: OdbcCommand, OdbcConnection,
OdbcDataAdaptor, odbcDataReader. Semnificaia acestora este aceeai cu a
claselor similare ale celorlali provideri.
Vom realiza dou aplicaii. Prima aplicaie se conecteaz la un fiier Excel
iar a doua la un server M y S q l.'
Folosim n mod intenionat metode diferite de conectare ODBC pentru cele
dou aplicaii: n caul primei aplicaii includem n stringul de conectare informaii
despre driver-ul Excel, iar pentru a doua aplicaie realizm o surs de date cu un
utilitar integrat sistemului de operare. Precizm c ambele metode pot fi folosite i
lucreaz la fel de bine pentru aplicaiile cu provider ODBC.

Aplicaia OdbcExcelExample

Vom reliza o aplicaie de tip Windows Forms care se conecteaz prin


providerul ODBC la un fiier E xce l 2003, n care pe prima foaie este un tabel.
Datele se citesc din sursa de date i se afieaz ntr-un control D ataG ridView .
Urmai indicaiile:

1. Deschidei Micosoft Excel i scriei tabelul:

A | B | C D I
1 IdProdus Denumire Pret Cantitate
2 1 Paine 2 200
3 2 Lapte 3 23
4 3 Iaurt 4 45
5 4 Cola 5 21
6
C apitolul 11. A p lic a ii cu baze de date n m o d elu l con ecta t 313

Salvai fiierul cu numele P ro d u se .xls n folder-ul C :\teste.

2. Creai n VCSE un nou proiect de tip Windows Forms, cu num ele


OdbcExcelExample.

3. Pe suprafaa formei plasai un control de :ip D ataG ridV iew .

4. n fiierul Form1.cs introducei directiva: asing System.Data.Odbc;

5. Dorim s populm controlul la ncrcarea formei. Deci tratm evenimentul


Load pentru form. Acionai dublu click pe suprafaa formei. n corpul
band/er-ului, introducei codul marcat cu Bold:

private void Forml_Load(object sender, EventArgs e)


{
// Setm numrul coloanelor i textul header-elor
dataGridViewl.ColumnCount = 4;
dataGridViewl.Columns[0]. HeaderText = "ID-ul";
dataGridViewl.Columns[1].EeaderText = "Nume";
dataGridViewl.Columns[2].EeaderText = "Pret";
dataGridViewl.Columns[3].EeaderText = "Nr Produse";

// Stringul de conectare
string connString =
@"Driver={Microsoft Excel Driver (*.xls)};
Driverld=790;
D b q = C :\teste\Produse.x l s ;
DefaultDir=C:\OdbcExcelExample\OdbcExcelExample\bin\Debug" ;

// Stringul de interogare
// [Foaiel$] poate fi [sheetl$] dup caz
string sql = @"select * fro m [Foaiel$]" ;

// Declarm variabilele conexiune i data reader


OdbcConnection conn = nulL;
O d b c D a t a R e a d e r reader = null;

// Crem conexiunea
using (conn = new OdbcConnection(connString))
{
conn.Open(); // Deschidem conexiunea
// Se execut interogarea
OdbcCommand cmd = new OdbcCommand(sql, c o nn);
reader = c m d .ExecuteReader();

// Tablou de stringuri. Reine valorile unui rnd


// din tabel
stringf] r = nuli;
314 P artea a III - a. B aze de date

// Metoda Read() avanseaz reader la un rnd nou


while (reader.Read())
{
r = new string[4]{ r e ader[0].T oString(),
r e ader[1].T oString(),
r e ader[2].T oString(),
reader[3].T oString() };
dataGridViewl.Rows.Add(r) ;
}
r e a d e r .C l o s e {);
} // using
}

6. Compilai i rulai cu F5.

La rulare obinei:

j ID-ul Nume Pret I Nr Produse fi



Uliiipaine :2 1200 '

12 | Lapte |3 ; 23

i3 ; Iaurt 14 45

|4 Cola 121 - :
* 1 i ; y
<

Observaii:
> Stringul de conectare precizeaz driver-ul Excel i ID-ul su. Dbg indic
sursa de date i calea de director, iar DefaultDir este directorul implicit.
> Codul C# este similar cu cel pentru provider-ii OLE DB sau SQL Server.

Aplicaia OdbcMySQL

Scopul acestei aplicaii este acela de a arta modul n care v putei conecta
la o baz de date M ySQ L cu C#, utiliznd provider-ul ODBC.
Diferena estenial fa de modul de conectare al aplicaiei anterioare
const n faptul c vom construi un Data Source Name (DSN) cu ajutorul unui
utilitar Windows. Acest DSN se utilizeaz apoi n stringul de conectare.
Separm tema n trei seciuni:

A) Instalarea serverului MySQL 5.0 i crearea unei baze de date


MySQL
Presupunnd c nu avei M ySQ L instalat i c nu ai mai lucrat cu aceast
baz de date, procedai dup cum urmeaz:
C apitolul 11. A p lica ii cu baze de d a is n m odelu l con ectat 315

> Intrai pe site-ul w w w .m ysq l.co r . La seciunea download, descrcai


fiierul m ysql-essential-5.0.45-w ir32.m si.
> Wizard-ul de instalare v cere anumite informaii, pe care le completai
selectnd urmtoarele opiuni (bifai check box-urile):
V Configure the MySQL Server now".
X Install as Windows Service
X Launch the MySQL Server Automatically".
Include Bin Directory in Windows PATH .
X Modify Security Settings. Introducei parola de root n cele dou
text box-uri.
V Enable root access from re n o te machines".
Create An Anonymous Accccm f.

n felul acesta, ai instalat MySQL S erver 5.0 ca s e rv ic iu W in d o w s care


starteaz n mod automat la pornirea caicuatorului. Avei un cont de adm inistrator
(root) i un cont A n o n ym o u s. Acesta din rm v permite s v conectai fr s
introducei user sau parol. Este bine s avei un asemenea user numai n
perioada de nvare, deoarece n practic creeaz probleme de securitate.
Acum serverul e lansat. l putem fo te i. Ne conectm cu clientul m ysq l.e xe
la serverul M ySQL pentru a crea o baz de date cu o tabel. Urmai indicaiile :

1. n taskbar-u\ sistemului de operare, click Start->Run. Introducei cm d i


apsai OK.
2. Tastai la promptul sistemului: m y s g l. n acest fel v-ai conectat ca user
Anonymous, deoarece nu ai specificat user i parol.
3. Tastai c r e a t e d a ta b a s e c la s a ;
Ai construit astfel o baz de date cl numele clasa.
4. Tastai show d a ta b a s e s ;
Vizualizai astfel bazele de date prehstalete i noua baz de date creat.
5. Introducei comanda u s e c la s a ; pentru a utiliza aceast baz de date.
316 P artea a III - a. B aze de date

6. Crem o tabel. Introducei comanda:

create table Elevi


(Nume v a r c h a r (15), Prenume varchar(15), Varsta int ) ;

7. Inserm cteva rnduri n tabel:

insert into Elevi values ('Blaga', 'Ionel', 25);


insert into Elevi values ('Horga', 'Lucian', 25);
insert into Elevi values ('Chifa', 'Ionel', 19);

8. Acum avem baza de date clase cu o tabel numit Elevi. Tabela


conine trei rnduri. V deconectai de la server cu comanda gui.

B) Crearea unui Data Source Name (DSN)

Informaiile necesare conectrii la o surs de date cu provider ODBC se pot


centraliza cu utilitarul ODBC Data Source Administrator. Ceea ce se obine se
numete Data Source Name (DSN).
Procedai astfel:

1. In bara de task-uri a sistemului de operare, accesai Start->AII Programs-


>Control Panel. Dublu click pe iconul Administrative Tools, apoi lansai
Data Sources(ODBC). Se deschide dialogul ODBC Data Source
Administrator.

2. n pagina U ser DSN, apsai butonul Add. Se deschide dialogul Create


New Data Source. Selectai din list driver-ul MySQL, apoi click pe butonul
Finish:
C apitolul 11. A p lica ii cu baze de date n m o d elu l con ectat 317

User DSN JSystem DSN j Fite DSNl| Drivers j Treeing j Connection Pooling | About j

User Data Sources:

Driver Add...

Select a driver for which ycu want to set up a data source.

Name I V
Microsoft Paradox Driver .db ) 4
Microsoft Paradox-Treibe f.d b I 4
Microsoft Text Driver ( .be; .csv) 4
Microsoft Text-T reiber ('.tit; " csv) 4
Microsoft Visual FoxPro Diver 6
Microsoft Visual FoxPro-T eiber 6
>rmect to
MySQLODBC 351 Driva 3
to you.
SQL Native Client 2 ;
SQLServer 2

<. L >
Help

Finish Cancel

3. Completai formularul de mai jos. n cmpul Data Source Name, introducei


ConexiurteMySQL. Dac dorii s v conectai ca user A n o n ym o u s, nu
este necesar s completai cmpurile U ser i P assw ord.

Connector/ODBC 3.5Tv12,f Add D ataSource.N am ep^f '

C o n n e c t c r/O D B C
M yS Q L

Login Connect Options !. Advanced


Database

Data Source Name .ConexiureMySQl


! The database to be current upon
Description ! 11 connecl

Server ,locaiho$t j O ptional Yes


;! Default [none]
User

Password

Database

j Test ] j Diagnostics >> j j Ok j | Cancel | [ Hclp~


318 P artea a III - a. B aze de date

Dac serverul MySQL nu este pe maina local, atunci n cmpul Server


trecei IP-ul /rosf-ului respectiv. De exemplu: 80.97.66.192

4. Apsai butonul OK pe dialogul de mai sus. Ai creat deja un DSN cu


numele ConexiuneMySQL, pe care l pasm stringului de conectare n
aplicaia C# care urmeaz.

C) Crearea aplicaiei C#

Aplicaia de tip Windows Forms se conecteaz la serverul M ySQL de pe


maina local i acceseaz baza de date clasa, creat la paii anteriori. Apoi
afieaz ntr-un control D ataG ridV iew datele din tabela E l e v i . Procedai astfel:

1. Creai n VCSE un nou proiect de tip Windows Forms, cu numele


OdbcMySQL.

2. Pe suprafaa formei plasai un control de tip D ataG ridV iew .

3. n fiierul Form1.cs introducei directiva: using System.Data.odbc;

4. Controlul se va popula la ncrcarea formei. Prin urmare, tratm evenimentul


Load pentru form. Acionai dublu click pe suprafaa formei. n corpul
handler-ului, introducei codul marcat cu Bold:

private void Forml_Load(object sender, EventArgs e)


{
dataGridViewl.ColumnCount = 3;
dataGridViewl.C olumns[0].HeaderText = "Numele";
dataGridViewl.Columns[1].HeaderText = "Prenumele";
dataGridViewl.Col u m n s [2].HeaderText = "Varsta";

string connString =
"dsn=ConexiuneMySQL;User=root;Password=iuliuta";
string sql = 0"select * from elevi";
OdbcConnection conn = n u l l ;
OdbcDataReader reader = nu l l ;

using (conn = new OdbcConnection(connString))


{
c o n n .O p e n ();
// Se execut interogarea
OdbcCommand cmd = new OdbcCommand(sql, c o nn);
using (reader = cmd.ExecuteReader())
{
s t r i n g [] r = null;
while (reader.Read())
{
C apitolul 11. A p lica ii cu baze de date n m odelu l conectat 319

r = new sfcring[3]{ r e ader[0].T oString{),


reader[l] .ToStringO ,
reader [2] .ToStringO }
dataGridViewl.Rows.A d d (r);

5. Compilai i executai cu F5.

La rulare, controlul D ataG ridV iew afieaz datele din tabela E le v i , obinute n
urma interogrii SELECT:

Numele Prenumele Varsta *>


Ionel \25
Horga Lucian 125
;Chifa Ionel !19
* V
<

Precizri:

M ySQL ofer propriul provider ODBC, numit MyODBC. Este driver-ul pe


care l-am utilizat la crearea DSN.
ADO.NET are un provider dedicat pentru MySQL, definit n spaiul de
nume M yS ql.D ata.M ySqlC lient.
* Nu am comentat codul, deoarece este similar cu cel ai aplicaiilor
anterioare cu provider ODBC.
320 P artea a III - a. B aze de date

C apitolul 12

Aplicaii cu baze de date n modelul deconectat


Dac ceea ce dorii este doar s citii i s afiai mari cantiti de date,
atunci un obiect de tip DataReader este foarte potrivit. n cazul n care trebuie s
efectuai mai multe operaii asupra acestor date i la final s actualizai baza de
date, atunci un reader nu este cea mai potrivit alegere, deoarece el parcurge
datele o singur dat, doar nainte i pentru fiecare operaie este nevoie s
construii un alt obiect de tip DataReader. Ceea ce trebuie s facei In aceste
situaii, este s folosii un dataset.
Un dataset este un obiect de tip System.Data.DataSet. Dafasef-urile
sunt capabile s depoziteze mari cantiti de date n memoria intern a
calculatorului. Un dataset v permite s preluai date din sursa de date, s nchidei
conexiunea cu baza de date, apoi s prelucrai datele offline, adic n modul
deconectat de la sursa de date. La final, cnd prelucrarea datelor s-a ncheiat,
baza de date se actualizeaz.
Un dataset memoreaz datele ntr-o colecie de tabele (obiecte de tip
DataTable) i de relaii ntre tabele.
n momentul n care construii un obiect de tip DataSet, acesta nu conine
date. Ca s primeasc date este nevoie de un obiect de tip DataAdapter. Un
DataAdapter este parte a furnizorului de date, n vreme ce un dataset este
exterior provider-ului. Fiecare provider are propriul su adaptor de date. Spre
exemplu, adaptorul provider-ului pentru SQL S e rv e re ste SqlDataAdaptor.

C onstruirea i utilizarea dataset-u rilo r

Ca s creai o instan a clasei DataSet, utilizai unul dintre


constructorii clasei:

DataSet ds = n e w D a t a S e t ();
DataSet ds = n e w D a t a S e t ( " n u m e D a t a S e t " ) ;

Al doilea constructor precizeaz numele dataset-ului. Primul constructor, atribuie


dafasef-ului numele NewDataSet.
n dataset, datele sunt organizate ntr-un set de tabele. Fiecare tabel se
memoreaz ntr-un obiect de tip DataTable. Fiecare obiect D a t a T a b l e consist
din obiecte de tip D a t a R o w i DataColumn, care pstreaz datele.
S presupunem c un dataset primete datele de la un SqlDataAdaptor.
Secvena standard de cod care construiete i umple dataset-ul este :

// Creeaz adaptorul de date


SqlDataAdapter d a = new S q l D a t a A d a p t e r ( s q l , conn);
C apitolul 12. A p lic a ii cu baze de date ut m o d elu l decon ectat 321

// Creeaz d a t a s e t - ul
DataSet ds = new DataSet);

// ncarc d a t a s e t-ul cu tabela elsvi. Dac exist i alte


// tabele n sursa de date, acelea nu se ncarc
da.Fill(ds, "elevi");

Aadar, constructorul clasei SqlDataAdaptor primete stringul de conectare i


conexiunea (referina la un obiect de tip SqLConnection), iar metoda Fiii a
adaptorului umple dataset-ul cu tabela elevi".
Exist nc dou versiuni ale constructoului dasei SqlDataAdaptor. Primul nu are
parametri, iar al doilea primete un obiect de tp SqlCoinmand:

SqlDataAdapter da = new SqlDataAdapter();


SqlDataAdapter da = new SqlDataAdapter(cmd);

Pentru a ncrca n dataset toate tabelele din baza de date, utilizai alt versiune a
metodei Fiii:

d a .Fiii(ds);

A cc e s a re a ta b e le lo r ntr-un d a ta s et

Un dataset poate s conin mai multe tabele. Acestea sunt obiecte de tip'
DataTable care se pot accesa indexat, ncepnd cu indexul 0. de exemplu :

// Obine tabela a treia din dataset.


DataTable dt = ds.Tables[2] ;

Alt variant este accesarea prin numele tabelei:

// Obine tabela produse


DataTable dt = ds.Tables["produse"];

A cc e s a re a r n d u rilo r i c o lo an e lo r n tr-o tabel

Rndurile unui unui obiect DataTable se obin din proprietatea Rows, care
suport indexarea :

// Obine al patrulea rnd al tablelei


DataRow r = dt.Rows[3];

Colecia de coloane a unui obiect DataTable se poate obine din


proprietatea Columns. Proprietatea suport operatorul de indexare, cu pornire de
ia 0:
322 P artea a III - a. B aze de date

// Obine coloana a 4-a


DataColumn col = dt.Columns[ 3 ] ;

// Obine coloana "Nume"


DataColumn col = dt.Columns["Nume"];

A cc e s a re a v a lo rilo r din tr-o tabel a u n u i dataset

Se utilizeaz proprietile Rows i Columns ale clasei DataTable:

// Obinem tabela dorit


DataTable dt = d s .T a b l e s ["produse"] ;

// Pentru fiecare rnd din colecie (din tabela produse)


foreach (DataRow row in dt.Rows)
{
// Pentru fiecare coloan
foreach (DataColumn col in dt.Columns)
C o n s o l e .Write(row[col]); // Accesare indexat a
// valorii unei'celule
Console.WriteLine();
}

P ro p ag area s c h im b rilo r din d a ta s et sp re baza de date

Am vzut c metoda Fiii () a clasei TableAdaptor umple un dataset cu


datele preluate din baza de date. Dac metoda este apelat dup ce s-a nchis
conexiunea, atunci Fill() deschide conexiunea, transfer datele n dataset i
apoi nchide conexiunea. Dac conexiunea era deschis nainte de apelul Fiii (),
atunci metoda las conexiunea deschis.
Modificrile operate asupra datelor unui dataset, se propag napoi n baza
de date la apelul metodei Update() a clasei TableAdaptor. Prezentm dou
versiuni ale acestei metode. Ambele returneaz numrul de rnduri updatate cu
succes.
Prima versiune actualizeaz baza de date opernd toate modificrile care s-au
fcut n dataset:

int Update(DataSet ds) ;

A doua versiune actualizeaz baza de date opernd toate modificrile care s-au
fcut n tabela transmis ca argument:

int Update(DataTable dt)


C apitolul 12. A p lica ii cu baze de date n m o d elu l deconectat 323

Actualizarea bazei de date se produce conform scenariului de mai jos:

// Creeaz adaptorul de date


SqlDataAdapter da = new SqlDataAdapter(sql, c o n n ) ;

// Creeaz datasei-ul
DataSet ds = new DataSet();

// Umple dataset-ul cu date din baza de date


da.F i l l (ds);

...
// Se modific datele n dataset
n

// Se propag modificrile n baza de date


t a .Update(ds);

Aplicaia UpdateDatabase

Aplicaia de tip Windows Forms acceseaz o baz de date SQL S erver


2005 i afieaz ntr-un control DataGridView datele dintr-o tabel. La apsarea
unui buton, modificrile operate de utilizator n celulele griduiui se propag n baza
de date.

1. Creai n VCSE un nou proiect de tip Windows Forms, cu numele


UpdateDatabase.

2. Pe suprafaa formei plasai un control de tip D ataG ridV iew i un buton cu


textul Salveaza i o etichet cu textul 0 rnduri afectate.

3. Adugai proiectului o baz de date cu numele Librrie. n acest scop, urmai


indicaiile subcapitolului Crearea unei baze de date in VCSE". Wizardul
propune numele LibrarieDataset pentru clasa pe care o genereaz.
Aceast clas motenete D a ta S e t, aadar Este Un dataset.

4. Adugai bazei de date L ib r rie tabela Crti, cu urmtoarea structur:

Column Name Data T ype Allow Nulls


>9 ZS' j int
Titlu n v a rc h a r(5 0 )
A u to r nvarchar(20) 0
P r t int 0
5. n fereastra Data Source, acionai click dreapta pe tabela Crti i selectai
Edit DataSet with Designer. Dup ce des/gner-ul se deschide, tragei tabela
Crti cu mouse-ul, din fereastra Data S ource pe suprafaa designerului:
324 P artea a III - a. Baze de date

Dat Sources , . 0 X S ta rtP ag e ' d b o .C tfti: Ta.,.\LlPPAR

/J i ifc___
- j j librarieD ataS et
i ^ Carb r Cod
iti\ Cod T*Ju
Jtel Titlu
A U Ol
bei Autor
Pre
ti Pre

'm FJ.G etData ()

Prin aceast aciune am cerut ajutorul mediului integrat, care a generat pentru
noi O clas CartiTableAdapter. Aceast clas conine un obiect de tip
SqlDataAdapter, un obiect de tip SqlConnection i un obiect de tip
SqlCommand, astfel nct nu mai trebuie s ne procupm de deschiderea
manual a unei conexiuni la server.

6. Deschidei n Editorul de Cod fiierul Form1.cs. n clasa Forml declarai


cmpurile:

// Declaram o referin la d a t a s e t
private Li b r a r i e D a t a S e t libDataSet = n u l i ;

// Referin la un obiect de tip C a r t i TableAdapter


private L i b r a r i e D a t a S e t T a b l e A d a p t e r s .C a r t i T a b l e A d a p t e r
ta = n u l i ;

7. Populm controlul DataGridview la ncrcarea formei. Deci tratm


evenimentul Load pentru form. Acionai dublu ciick pe suprafaa formei. n
corpul handler-ului, introducei codul marcat cu Bold:

private void Forml_Load(object sender, EventArgs e)


{
// Xnstaniem adaptorul de date. Observai c este
// necesar s specificm spaiul de nume n care este
// definit clasa CartiTableAdaptor
ta = n ew
L i b r a r i e D a t a S e t T a b l e A d a p t e r s .C a r t i T a b l e A d a p t e r ();

// Crem ur. d a t a s e t
l i b D a t a S e t = new L i b r a r i e D a t a S e t ();

// Umplem d a t a s e t - u l cu datele din tabela Crti


t a .F i i i ( l i b D a t a S e t . C r t i ) ;

// bs permite legarea controlului dataGridViewl


// la sursa de date din d a t a s e t
B i n d i n g S o u r c e bs = n e w BindingSource(libDataSet,
"Crti");
V
I

C apitolul 12. A p lica ii cu baze de date n m o d elu l deco n ecta t 325

// Legarea se face prin proprietatea DataSource


dataGridViewl.DataSource = bs ;

8. La acionarea butonului Salveaza, se transm't modificrile din dataset n baza


de date. Tratm evenimentul C lick. Acionai dublu click pe buton. Metoda de
tratare se editeaz astfel:

private void buttonl_Click(object -sender, EventArgs e)


{
// Propagm modificrile spre baza de date.
int afectate = t a .Update(libDabaSet.Crti);
labell.Text = afectate + " rnduri afectate";

9. Compilai i rulai cu F5.

Aplicaia afieaz forma:

0 rnduri afectate

Cod Titiu Autor Piet


ffip a j|io n LiviuRebreanu : 32
: 1437 Rou si Negru . Stendhal ; 33 f
13512 QuoVadis Sienkiewicz ! 35
I S423 :Ana KArenina Tolstoi 48 :
* I V

< >

c spre exemplu operm modificri n celuiee din rndurile 3 i 4, iar apoi


sm Salveaza, obinem:

, Cod Titlu Autor Pret A


231 Ion .LiviuRebreanu i 32 ;
: 1437 Rou si Negru Stendhal .33
3512 . Quo Vadis Henrik Sienkiewicz : 35
6423 : Ana Karenina
*
< .! >
326 P artea a III - a. B aze de date

La o nou rulare cu F5 vei constata c modificrile aduse bazei de date sunt


persistente.

Observaii:
* Mediul VCSE creeaz cele dou fiiere ale bazei de date (.mdf i .LDF) n
folderul de baz al aplicaiei, la un loc cu fiierul .csproj. n momentul n
care facei B u ild cu F5 (modul depanare), se face o copie a celor dou
fiiere n folderul \Bin\Debug, iar aplicaia se lanseaz i lucreaz cu
aceste copii. La noi rulri cu F5, nu se mai face B u ild dac nu ai adus
modificri n cod, ci numai lansri n execuie. Constatai c baza de date
din \Bin\Debug se actualizeaz. Dac ai operat modificri n cod, atunci la
un F5 se face i B uild i baza de date original se copiaz peste cea din
\Bin\Debug.
* Stringul de conectare se genereaz n mod automat la crearea bazei de
date cu ajutorul mediului integrat. Se poate vizualiza astfel: n Solution
Explorer, click dreapta pe fiierul app.config i selectai Open. Vei
constata informaiile de conectare se pstreaz n format XML.
Atribuirea dataGridViewl.DataSource = b s ; leag controlul de
dataset, astfel nct orice modificare operat in celulele controlului, se
transmite n mod automat tabelei din dataset.

D ataset-u rile i X M L

Cnd lucrai cu dafasef-uri, avei posibilitatea s salvai datele local, ntr-un


fiier de tip XML, astfel nct informaiile s persiste i n alt loc dect n baza de
date dup ncheierea sesiunii.
Salvai datele cu ajutorul metodei W r i t e X m l () a clasei D a t a s e t astfel:

d s . W r i t e X m l ( @ " C :\ d a t e .xml");

Cnd deschidei o nou sesiune a aplicaiei, avei alternativa de a rencrca n


dataset datele preluate din fiierul XML. Citirea se face cu metoda ReadXml ( ) :

d3.ReadXML("C:\date.xml");

Exemplu:
Ne ntoarcem la aplicaia UpdateDatabase, realizat anterior. Introducei ca
ultim linie n corpul metodei de tratare a evenimentului C lick pentru butonul
Sa/veaza, apelul:

libDataSe t . W r i t e X m l (@"C: \carti__bune .xml") ;

Rulai cu F5, apoi cutai fiierul carti_bune.xml. Vei constata c toate


informaiile din dataset s-au salvat n format XWIL.
C apitolul 12. A p lica ii cu baze de d a te n m o d elu l deconectat 327

C ontroalele i legarea d a te lo r

Anumite proprieti ale controalelor se pot lega la o surs de date. Sursele


de date sunt diverse: o proprietate a altui control, o celul, un rnd sau o tabel
ntr-un dataset, sau o simpl variabil. Conceptul se numete Data Binding. Dup
ce au fost legate, valorile din sursa de date schimb valorile din proprietatea legat
i invers.
Controalele Windows Forms suport dou tipuri de legare a datelor (data
binding):
Legarea sim pl.
* Legarea com plex.

Legarea simpl a datelor


Acest tip de legare v permite s ataai o proprietate a unui control la o
sin g u r valoare din sursa de date. Este util pentru controale ca T extB ox sau
Labei, care afieaz o singur valoare. Aplicaia urmtoare arat cum putei lega
proprietile a dou controale.

Aplicaia SimpleDataBinding

1. Creai un nou proiect WindowsForms cu numele SimpleDataBinding.

2. Pe suprafaa formei plasai dou controale: un TextBox i un Labei.

3. n constructorul clasei F orm l, introducei codul evideniat Tn B old:

public F o r m l ()
{
InitializeComponent();
// Legm proprietatea Text a butonului (primul
// parametru) de proprietatea Text a text box-ului
buttonl.DataBindings .Add("Text", textBoxl, "Text");
}

4. Tratm evenimentul C lick al butonului. Acionai dublu click pe buton i


introducei codul marcat n Bold, n metoda de tratare:

private void buttonl_Click(object sender, EventArgs e)


{
buttonl.Text = "Salutare!";
!

5. Rulai cu F5.

Facei click pe buton, apoi un click n text box ca s primeasc focusul. n text box
se afieaz Salutare! . Dac introducei text n textbox, eticheta butonului se
modific corespunztor.
328 P artea a III - a. B aze de date

Salutarei

jSalutaref

Click pe buton Editare n text box

Legarea complex a datelor

Aplicai acest tip de legare atunci cnd vrei s afiai o list de valori din
sursa de date. Controalele care suport legarea complex sunt DataG ridView ,
ListB ox, C om boB ox, C h e cke dL istB o x. Aceste controale au de proprietatile
DataSource i DataMember, cu ajutorul crora le putei lega la tabela unei baze de
date, astfel:

dataGridViewl.DataSource = librarieDataSet;
dataGridViewl.DataMember = "crti";

n exemplu, proprietii DataSource a gridului i se atribuie dataset-ul aplicaiei, iar


proprietii DataMember i se atribuie numele unei tabele din dataset. Aceste setri
se pot face uor n fereastra P roperties, aa cum vom vedea n continuare.

Aplicaia Com plexDataBindingl

Aplicaia utilizeaz utilizeaz facilitile mediului integrat pentru a lega


proprietatile unui control D ataG ridV iew la o tabel a unei baze de date SQL
Server 2005 Express. Urmai paii:

1. Creai n VCSE un nou proiect de tip Windows Forms, cu numele


ComplexDataBinding 1.

2. Adugai proiectului o baz de date cu numele S pectacole. n acest scop,


urmai indicaiile subcapitolului Crearea unei baze de date in VCSE.
Wizardul propune numele SpectacoleDataSet pentru clasa pe care o
genereaz. Aceptai acest nume.

3. Adugai bazei de date S pectacole tabela Concerte, cu urmtoarea


structur:
C apitolul 12. A p lic a ii cu baze de date n m odelu l decon ectai 329

Column Name Data Type Allow Nulls

^ JjIDConcert I in t
TipConcert n varchar(20) 0
SustinutDe nvarchar(50)
Data datetime
Locaie nvarchar(20) 0
Completai cteva rnduri cu date n tabel.

4. n fereastra Data S ource acionai click dreapta pe tabela Concerte i


selectai Edit DataSet with Designer. Dup ce designez-ul se deschide, tragei
tabela Concerte cu mouse-ul din fereastra Data S o u rce pe suprafaa
designerului. Prin aceast aciune am cerut ajutorul mediului integrat, care a
generat pentru noi o clas ConcerteTableAdapter.

5. n View Designer selectai forma, iar n fereastra D ata S ources deschidei


lista ataat tabelei Concerte i selectai DataGridView.

; ' --
rj g?) SpectacoieDataSet
;t ,-J E S 3 v
g DataGridView

; ItetBox

; 23 Dfaite

6. Urmeaz o aciune simpl: n fereastra Data S ources selectai cu mouse-ul


tabela Concerte, apoi o tragei peste form. Pe suprafaa formei apare un
control D ataG ridV iew , cu celulele legate la tabela Concerte:

dbo.Concerte:..,ECTACOLE.MDF) ; SpectacoieOataSet.xsd F o rm l.c s [D esign]*

V )., U1 n J IP, I -

spectacokOataSet - j ccrcerteBirvingSourc jConcertsTai^eAdaptef

J^tabteA daptarM anager concetteBndlngNavJQator


330 P artea a III - a. Baze de date

Observai apariia n designer tray a ctorva referine la obiecte de tip


TableAdaptor sau BindingNavigator.

7. Rulai cu F5.

Vei obine:

i ID Concert TipConceit SustinutDe Data

Rock i Metailica . 12.03.2009

12 Hip Hop i Eminem , 04.07.2009

3 House ; Mickey Oliver 15.11.2009

4 Country ; Martina McBride 24.02.2009


*- !
< V

ncercai s in g u ri:

n proiectul anterior, tergei din designer tray apsnd tasta delete toate
referinele. tergei i gridul de pe form. n fereastra Data S o u rc e s , selectai
Details, apoi tragei cu mouse-ul tabela pe suprafaa formei. Pe suprafaa formei
vor aprea patru controale de tip T e xtB o x i un D ateTim ePicker. Fiecare control
este legat la una dintre coloanele tabelei.
H r n r a j f f ' ~ "W w m fnm

1 H + j 2 of 4

IDConcert: :|2

Tip Concert: HipHop ______________ j

Susinut De: ! Eminem 1

Data: 4 iulie 200S x i

Locaie: | Bucureti
-- - ------------------------------1

Toate controalele indic acelai rnd din tabel. Navigarea de la un rnd la altul se
face cu ajutorul butoanelor sgeat din controlul T o o lS trip din partea de sus a
formei.

Aplicaia Com pIexDataBinding2

Modificm proiectul anterior astfel nct s legm proprieti ale controalelor


L istB o x i T e x tB o x la baza de date, ca s fie posibil editarea datelor i
trasmiterea modificrilor bazei de date.
C apitolul 12. A p lica ii cu baze de date n m odelu l decon ectat 331

Paii 1, 2, 3, 4 sunt identici cu cei ai aplicaiei precedente. Schimbai doar


numele proiectului: ComplexDataBinding2.

5. n Dataset Designer, acionai click dreapta pe itemul C oncerte T a b le A d a p te r


i selectai Configure...

S ta rt Page . d bo.C oncerte:...E C T A C O LE .M D F)

f ID C o nce rt
TipC oncert
S ustinutD e
D ata
Locaie

Configurm adaptorul, deoarece vom apela metoda U p d a te d pentru


actualizarea bazei de date i aceast metod utilizeaz interogri SQL n
acest scop. Vom genera interogrile n mod automat. Apsai butonul Next al
primului dialog. Al doilea dialog ne spune c va genera pentru noi. metodele
Pill, GetData, Insert, Delete i Update. Apsai din nou Next, apoi pe
ultimul dialog, Finish.

6. Plasai n Form Designer pe suprafaa formei un control L istB o x, patru


controale T extB ox, un Labei i un buton :

i l
O-

O o

O'

0 RNDURI AFECATATE Salveaza

7. Din T o o lb o x alegei i plasai pe suprafaa formei, componentele:


C oncerteT ableA d ap te r i B in d in g S ource. Referinele se creeaz automat
i apar n designer tray.
332 P artea a III - a. B aze de date

:?<**&; i/C_. c, ir-J * J S f c ^ tP a g e d b o .C o n c e rte :...E C T A C O U t.M D F ) : Spe


! Complcx0ta8indingl Component
Pointer
| ijjfc SpectocoteDataSet
! Concert TableAdapter
19 TableAdapterManager
| -j&JM Window* ;
.'ii Common Control* ... .1;. :
.LCootolner* ....
;. a Menu* & Toolbar*
ij8. Pata
j j > Pointer |i
j 3?j DataSet
j J DataGrldView ;
bnnqSajrcel ! 3, corcerteTabteAdapter !
j BindingScurce ;.

8. Selectai n designer tray bindingSourcel. n fereastra P ro p e rtie s atribuii


proprietii DataSource valoarea SpectacoleDataSet, iar proprietii
DataMember, tabela Concerte:

tJ-- A 1 -1
(Name) bindingSourcel 't . z *
AllowNew True :S (ApplicationSettings)
DataMember 1 (Name) b in d in g S o u rc e l
(none) ! AllowNew True
BataMember:;v*WJ3f I Concerte
B i j J Other Data Sources C None
S i j j ] Project Data Sources ASSESS
?] SoectacoleDataSet

9. Selectai controlul L istB o x. Acionai click pe sgeata dreapta sus. n


fereastra care se deschide, facei seleciile ca n figur:

|0 Use data bound items

I D ata Binding Mode

Data Source jb tfid in g S o u r c e l'-


V-------------- - EM
.------------- ^
: SustinutDe ^ ii
:------------ --- -------------
0 RNDURI AFECATA: Value Member ____ r!
11 Selected Value : (none)
C apitolul 12. A p lic a ii cu baze de date n m odelu l d eco n ecta t 333

10. Selectai controlul T extB o x cel mai de sus. In fereastra P ro p e rtie s, expandai
itemul Data B in d in g s i setai proprietatea Text la valoarea SustinutDe :

;B (DataBindings)
(Advanced)
Tag (none)
(none) V

if] IDConcert
[H TipConcert
jO SustinutDe

11. Executai aceleai operaii de la pasul 10, pentru urmtoarele trei textbox-uh,
cu diferena c vei lega proprietatea Text la celelalte coloane ale tabelei.

12. La ncrcarea formei, vom umple dataset-u!. Dublu click pe suprafaa formei,
n Editorul de Cod scriei:

private void Forml_Load(object sender, EventArgs e)


{
// Fill() ncarcdatele din b^za de date n datset
c o n c e r t e T a b l e A d a p t e r l .F i i i ( s p e c t a c o l e D a t a S e t .C o n c e r t e ) ;
}

13. La click pe butonul Salveaz, transmitem bazei de date modificrile fcute de


utilizator. Dublu click pe buton. Scriei n metoda handler.

private void buttonl_Click(object sender, EventArgs e)


{
// Aplicm sursei de date modificrile fcute
bindingSourcel.EndEdit();

// Updatm baza de date


int a f e c t a t e =
concerteTableAdapterl.Update(spectacoleDataSet);

l abell . T e x t = afectate + " rnduri afectate";


}

14. Rulai cu F5.

Se obine:
334 P artea a III - a. B aze de date

H Q
1
| Metallica [Eminem j
| Mickey Olivei j Hip Hop j
: Martina McBride ------- !
i j Bucureti i
04.37.2003 - 1
1

1 rnduri afectate Salveaza

La click n list box, textele se modific n controalele text box n mod automat,
astfel nct toate controalele de pe form indic acelai rnd din tabel. Valorile
celulelor tabelei se pot edita din text box-uri, iar modificrile n baza de date sunt
persistente.
C apitolul 13. R elaii ntre tabele 335

C ap itolul 13

Relaii ntre tabele


ntre tabelele unei baze de date (i a unui datasef) pot s existe relaii de tip
printe-copil. S presupunem c n baza de date S c o a la .m d f exist dou tabele:
C la s e i E le v i . O clas are mai muli elevi. Construim deci o relaie ntre cele
dou tabele, de tip una la m ai multe (one to many).

C onstrn gerea C heie S trin-C heie P rim ar

n tabela clase avem un cmp clasa, care reprezint numele clasei (ex.
Xll-B). l setm cheie primar. n tabela Elevi introducem un cmp cu acelai
nume. Nu dorim s existe elevi pentru care cmpul clasa are o valoare care nu
exist n tabela Clase. Impunem o constrngere de tip foreign key-prim ary key.
Este o constrngere referenial. Clase este tabela printe, iar Elevi, tabela
copil. Un rnd al tabelei printe poate s refere multiple rnduri n tabela copil.

Aplicaia coala
Aplicaia creeaz baza de date i tabelele precizate mai sus, impunnd o
constrngere de cheie strin-cheie primar. Dac un rnd n tabela clase se
terge, atunci dorim s se tearg toate rndurile corespunztoare din tabela
Elevi pentru a pstra integritatea datelor. Vom seta regula de tergere pentru
aceast relaie: N CASCAD.

Atentie
t !
V sugerm s nu ocolii acest proiect, deoarece pe structura lui vom lucra
n temele urmtoare, unde va fi dezvoltat i completat.

1. Realizai n VCSE un proiect de tip Windows Forms, cu numele coala.

2. Adugai proiectului o baz de date cu numele coala. n acest scop, urmai


indicaiile subcapitolului Crearea unei baze de date in VCSE. Aceptai
numele ScoalaDataSet pentru clasa de tip DataSet care se genereaz.

3. Adugai bazei de date coala tabelele clase i Elevi cu urmtoarele


structuri:
Tabela Clase
Column Name Data Type Allow Nulls

I Clasa nvarchar(50)
NrElevi int
Diriginte nvarchar(50) 0
336 P artea a III - a. Baze de date

Tabela E l e v i
Column Name Data Type Allow Nulls
; K? IdElev int
i Nume nvarchar(50) 0
: Media real 0
Dup completarea schemei, introducei cteva rnduri n fiecare tabel.

4. n D atabase E xp lo re r, click dreapta pe Database Diagrams. n dialogul Add


Table selectai pe rnd tabelele Clase i Elevi i apsai butonul Add.
Diagramele celor dou tabele apar n designer.

dbo.D iagram l...\SC O ALA.M D F)* Forml.cs [Design] (S tartP age

Clase m a o m m
! V Clasa 9 IdElev
! NrElevi Nume
' Diriginte Media
Clasa

5. Introducem constrngerea de cheie strin. Punctai cu mouse-ul .n cmpul


clasa din tabela clase i tragei innd butonul apsat pn pe cmpul
Clasa al tabelei Elevi. Se deschide un dialog care identific cheia primar,
cheia strin i numele relaiei care se creaz:

Relationship name:

Lass*ss_
Primary key table: Foreign key table:

i Clase Elevi

Clasa Clasa

6. Apsai OK s nchidei dialogul anterior. Urmtorul dialog v permite s


stabilii regulile relaiei de cheie strin. Setai pentru Deiete i Update regula
Cascade, apoi apsai OK:

;B INSERT And UPDATE Specification


Cascade
Update Rule Cascade
El Id e n tity
; (Name) FK Elevi Clase
;. Description____
C apitolul 13. R elaii n tre tabele 337

7. n designer, relaia se vizualiteaz ca o linie cu o cheie spre tabela printe i


simbolul infinit spre tabela copil (relaie una la m ai multe). Salvai diagrama
sub numele D iagram l.

8. Plasai pe suprafaa formei un control M enuS trip, un S p litC o n ta in e r, iar n


cele dou panouri ale acestuia, cte un control DataGridView:

9. Adugai meniului Clase, opiunile: Adauga clasa, terge clasa, Modifica


clasa. Adugai meniului Elevi, opiunile: Adaug elev, terge elev, Modifica
elev.
Adugai meniului Rapoarte, opiunile: Diriginti-clase i Media pe clase.

10. Configurm dafasef-ul aplicaiei cu ajutorul Wizard-ului. n fereastra Data


S ources, acionai click dreapta pe itemul ScoalaDataSet i selectai Configure
DataSet with Wizard. n dialogul care se deschide, selectai toate categoriile:
tabele, vederi, proceduri stocate, funcii, apoi apsai Finish.

11. Din fereastra Data Sources, tragei cu mouse-ul tabela Clase peste gridul din
stnga al formei, apoi tragei tabela Elevi peste gridul din dreapta.

12. Rulai cu F5.

La rulare, se obine:

m im saB S S^m
[ . h O a s e . ^ a ^ ^ l a i w a r ^ 5^ ' ' x * C '. - - ' * . j

1 ' Clasa NrElevi Diriginte A ! IdEiev Nume Medie Clasa A

g _Vernescu f j f p B M Alinuta j 9.99 IX 2

iX 129 Colcer ;3 ; Marcel ~ '7.75 :> i a,


1 1X1 : 26 ;Vaida .! 4 i Georgel i 5,51 X '

I XI! |31 Berende S T udorel I8.9 X

l< > ~
St
< . >'
71
338 P artea a III - a. B aze de date

Interogri. P ro c e d u ri stocate.
Continum s dezvoltm proiectul coala, nceput anterior. Opiunile din
meniuri nu sunt nc funcionale. Ca s fie, trebuie s interogm baza de date.
Dac vrem s introducem noi clase sau elevi, avem nevoie de comanda SQL
i n s e r t .Cnd vom dori s tergem din baza de date o clas sau un elev, aplicm
d e l e t e ,iar cnd modificm datele ne trebuie u p d a t e .
O ntrebare fireasc ar fi: cum trimitem aceste interogri serverului de baze
de date, din codul nostru C# ? O prim variant este s manevrm clasele
SqlConnection, SqlCommand, SqlDataAdapter. Este laborios dac Scriem tot
codul necesar.
Din fericire, mediul integrat ne ajut mult n aceast privin. Vom genera n
mod automat metode C# pentru clasele claseTableAdapter i
EleviTableAdapter. Aceste metode ncapsuleaz interogrile SQL sau
proceduri stocate. In continuare adugm interogri aplicaiei coala.

Aplicaia coala - adugarea interogrilor

1. n S o lu tlo n E xp lo re r, acionai dublu click pe itemul scoalaDataSet.xsd. n


Dataset Designer, pe diagrama tabelei clasa, click dreapta pe
ClaseTableAdapter. Selectai Add Query...

2. Dialogul urm tor v permite s generai o metod care conine o interogare


SQL, o procedur stocat, sau o metod care apeleaz o procedur stocat
existent:

T ableA dapter Q u ery C onfiguration W izard

Choose a Command Type


TableAdapter query uses SQL statements or a stored procedure.

How should th e T a b le A d a p te r q ue ry access th e database?

0 Use SQL s ta te m e n ts

Specify a SELECT statement to load data.

O C rea te new s to red procedure

Specfy a SELECT statement, and the wizard will generate a new stored procedure to select records.
C apitolul 13. R ela ii ntre tabele 339

Selectai Use SQL statements i apsai CK.

3. n dialogul urmtor, selectai INSERT i apsai Next:

C h o o se a Q u ery Type
Choose the type of Query to be generated
t t
W hat typ e o f SQL query would you like to use?

O SELECT which re tu rn s rows


Returns one or many rows or columns.

O SELECT w h ic h re tu rn s a s in g le va lu e
Returns a single value (for example, Sum, Count, or a ry other aggregate function),
O UPDATE
Changes existing data in a table.
O d elete

Removes rows from a table.


INSERT
Adds a new row to a table.

4. Dialogul care se deschide propune o interogare INSERT TO pentru adugarea


unei clase. Apsai butonul Query Buitcer...

T b teA d ap ter Q u e ry C onfiguration W izard -

Specify a SQL INSERT statement u


The INSERT statem ent will be used by the query.
HP
Type your SQL statem ent or use the Query Builder to construct it. W hat data should be loaded into the
table?
W h a t d a t a s h o u ld t h e t a b le lo a d ?

I INSERT INTO [d b o ].[Clase] ([Clasa], [NrElevi], [D irigirte]) VALUES (Clasa, NrElevi, Diriginte); 1
; SELECT Clasa, NrElevi, Diriginte FROM Clase WHERE (Clasa - Clasa)

[ Query Builder..

5. Se deschide dialogul Query Builder. Acesta este un instrument util, pentru c


v permite s selectai pe diagrama Clase cmpurile pe care ie nserai, iar
codul se genereaz automat. Evident, putei edita i manual:
340 Partea a III - a. Baze de date

jil
* (All Columns)
t+jdasa
f+jNrElevi
1+)Diriginte
v.:
Y.

< ".'.1 >

New Value A
Column
; Clasa @Clasa
NrElevi @NrE!evi V

INSERT INTO Clase "'' " " " ....................... "


(Clasa, NrElevi, Diriginte)
VAIUES (@Clasa,@NrElevi, Diriginte)

7 -" T T -? ...... - ....... ........................ .......... -..... ' ... ......:

Execute Query [ OK I . Cancel

Ai remarcat modul n care se specific valorile rndului care se insereaz? De


fapt, @Clasa, @NrElevi, @Diriginte reprezint numele p a ra m e trilo r
m etodei insert() care se va genera, ca membr a clasei
ciaseTableAdapter. n dialogul urmtor, setai numele m e to d e i:
InsertClasa.

6. Ca s introducei datele, creai o nou form. n S o lu tio n E xplorer, click


dreapta pe numele proiectului, selectai Add, apoi Windows Form... Numii
forma FormlnsertClasa:

Clasa

Nf elevi : !

Dirig ;___________ j
I Adauga j

7. Din T o o lb o x, selectai componenta c la s e T a b le A d a p te r i piasai-o pe


suprafaa formei. n designer iray, apare referina claseTableAdapterl.
Facem acest lucru deoarece avem nevoie de adaptor pentru apelul I n s e r t ( ) ,
C apitolul 13. R ela ii ntre tabele 341

dar n clasa Forralnsertcla.sa nu este vizibil adaptorul


claseTableAdapter, definit n class Forml.

8. Acionai dublu ciick pe butonul Adaug. n metoda de tratare, scriei:

private void buttonl_Click(object sender, EventArgs e)


{
if (textBoxl.Text = "" ! I textBox2.Text = " j|
textBox3.Text = ""I
{
Me s sageBox.Sh o w (
"Nu ati completat toate cmpurile!");
return;
}

claseTableAdapterl.Inserc{textBoxl.Text,
i n t .P a r s e (textBox2.T e x t ) , textBox3.T e x t ) ;
Close () ;
}

9. Pe forma F o rm l, acionai dublu click pe opiunea Adauga clasa. n metoda de


tratare scriei:

private void adaugaClasaToolStripMenu!tem_Click(


object sender, EventArgs e)
{
// Instaniem forma ForalnsertClasa
FormlnsertClasa flnsCl = new FormlnsertClasa() ;
fXnsCl .ShowDialog();
// Acum n baza de date avem un rnd nou
// ncrcm datele din baza de date n dataset
claseTableAdapter.Fiii(scoalaDataSet.Clase);
}

10. Compilai i rulai cu F5.

La rulare, introducei clase cu nume diferite, cu ajutorul opiunii Adauga clasa :

Clasa . NElevi Dmgint ^ [ ; IdEIev Nume Media Clasa

9,99 IX J
v.
!IX 23 Vemescu 7,75 XII

lX 29 Colcer Clasa: fv ; '5,51 X

:XI '2 6 ;Va!da NrElevi: ;26 j 8,9 X


Diriginte, ; Danciu Elena j >

j Adauga j

'
342 P artea a III - a. B aze de date

Generarea procedurilor stocate

0 procedur stocat (stored procedure) consist dintr-un grup de comenzi


SQL adunate sub un nume. Comenzile au fost anterior create i stocate pe
serverul de baze de date. Procedurile stocate sunt compilate o singur dat i
apoi aplicaia client le poate apela de cte ori este necesar. Sunt foarte rapide.
Accept date prin parametri de intrare. Datele sunt specificate n timpul execuiei.
n aplicaia anterioar, nainte de apelul insert), am verificat dac toate
cmpurile sunt completate. Nu am verificat alte dou aspecte importante: dac
valoarea introdus pentru N r Elevi este sau nu un numr ntreg i dac clasa
introdus nu exist deja n baza de date. n ambele situaii, se arunc excepii.
Prima problem se rezolv relativ uor, cu ajutorul metodei
int.TryParse (string, int), care ncearc s converteasc primul argument
n numr, iar dac nu reuete retureaz false.
A doua problem necesit interogarea bazei de date (un SELECT) pentru a
vedea dac clasa nu exist deja n baza de date. Pentru aceasta putem genera o
nou metod n clasa adaptorului, ns vom prefera s crem o procedur stocat,
pentru a vedea cum se procedeaz. Urmai indicaile :

* n Dataset Designer, selectai diagrama Clase i facei click dreapta pe


adaptorul ClaseTableAdapter. Selectai Add Query, apoi n dialogul care
apare, selectai Create new stored procedure:

mm
Choose a Command Type
TableAdapter q ue ry uses SQL statements or a stored procedure.

How should the TableAdapter query access the database?


O Use SQL statem ents
Specify a SELECT statem ent to load data.

0 Create new stored procedure


Specify a SELECT statem ent, and the wizard will generate a new stored procedure to select records.

O Use existing stored procedure

n dialogul urmtor, alegei SELECT wich returns a single value:

Choose a Query Type


Choose the typ e o f q uery to be generated

W hat type of SQL query would you like to use?


O SELECT which returns rows
Returns one or many rows or columns.

0 SELECT which returns a single value


Returns a single value (fo r example, Sum, Count, or any oth e r aggregate function),
O UPDATE
C apitolul 13. R ela ii n tre tabele 343

n dialogul urmtor, editai interogarea astfel:

Generate the stored procedure


The SELECT statem ent will be used to create a store] procedure th a t wiU be called by
the query.

Type your SQL statem ent or use the Query Builder to c o n tru c t it. W hat d ata should be loaded Into the table?
W hat d ata should the table load?
SELECT COUNTS) FROM Clase - - - ">
WHERE Clasa @Clasa[ j

Am adugat clauza WHERE. Parametrul g c ia s a devine n mod automat


parametru de intrare al procedurii stocate, c o u n t () returneaz numrul de
rnduri care conin clasa @ ciasa.

Apsai butonul Next i stabilii numele procedurii stocate MaiExistaClasa.


Putei s pstrai n dialogul urmtor acelai nume i pentru funcia care
apeleaz procedura stocat. Apsai butonul Finish.

Dac vrei s vedei sau s editai codul procedurii stocate, mergei n


D atabase E xplorer, expandai itemul Stored Procedures i dubiu click pe
procedura MaiExistClasa:

d b o .M a iE x ista ,..L A \SC O A L A .M D F ) s ta rt Page ; Form Lcs Fo rm l.cs [D<


|a l TER PROCEDURE dbo.MaiExistaClasa
(
Ciasa nv a r c h a r (50)

S
SET NOCOUNT ON;
SELECT C O U N T (*) FROH Clase
UHERE Clasa Clas;

Acum suntem n msur s completm codul metodei b u t t o n l _ c l i c k :

private void buttonl_Click(object sender, EventArgs e)


{
if ( t e x tB o x l.T e x t == "" |! te x tB o x 2 . T e x t = "" ||
te x tB o x 3 . T ext = " )
{
M e s s a g e B o x .S h o w (
"Nu ati completat toate cmpurile!");
return;
)
344 P artea a III - a. B aze de date

int intreg = O ;
if (!int.TryParse(textBox2.Text, out intreg))
{
MessageBox.S h o w (
"Nr elevi trebuie s fie numr intreg!);
return;
}

i f ( (int)claseTableAdapterl.MaiExistaClasa(
textBoxl.Text) == 1)
{
MessageBox.S h o w ("Clasa exista deja!");
return;
}
claseTableAdapterl.I nsert(textBoxl.T e x t ,
i n t .P a rse(textBox2.T e x t ) , textBox3.T ext);
C l o s e ();
>

IM P O R TA N T! . . _
Metoda I n s e r t , ca dealtfel toate metodele care conin interogri, pot s
arunce excepii. De aceea, trebuie incluse n blocuri try-catch.
Noi nu am fcut-o aici, pentru claritate.

Tem de lucru:
Implementai facilitatea de adugare a unui nou elev n baza de date la
selectarea opiunii Adauga elev din meniul Elevi. Trebuie s creeai o funcie
suplimentar care interogheaz baza de date determinnd dac valoarea pe care
o introduce utilizatorul pentru cmpul Clasa exist sau nu n tabela clase.

tergerea unei nregistrri din baza de date

Pentru a terge o clas din baza de date, este nevoie de o funcie care
ncapsuleaz comanda SQL DELETE. Procedm astfel:

1. Adugai o nou form cu numele FormDeleteClasa:

I FormDeleteClasa ^ (

Clasa care se terge: | j

( terge j
__________________________
C apitolul 13. R e ia i ntre tabele 345

2. Din T oolbox, selectai componenta C l a s e T a b l e A d a p t e r i plasai-o pe


suprafaa formei FormDeleteClasa. n designer tray, apare referina
claseTableAdapterl.

11. n S o lu tio n E xplorer, acionai dublu dick pe itemul S c o a la D a ta S e t.x s d . n


Dataset Designer, pe diagrama tabelei Clasa, click dreapta pe
ClaseTableAdapter. Selectai A dd Query...

12. n primul dialog, selectai Use SQL tatem ents. Apsai Next. n al doilea
dialog, selectai DELETE. n Query Bufder, editai interogarea astfel:

DELETE F R O M Clase
WHERE (Clasa = @Original_Clasa)

@ O r ig in a l_ c ia s a este numele parametrului de intrare al funciei care se


genereaz.

13. Stabilii n urmtorul dialog, numele funciei: D e le te C la s a .

14. Pe Formi, n View Designer, efectuat dublu click pe opiunea stergeClasa.


n corpul handler-ului introducei:

private void stergeClasaTool5tripMenuItem_Click(


object sender, EventArgs e)
{
FormDel e t e C l a s a fDelCl .= new F o r m D e l e t e C l a s a ();
f D e l C l .S h o w D i a i o g ();

// Rencrcm cele dou tabele din dataset


/ / c u datele modificate din baza de date
ClaseTab l e A d a p t e r . F i l l (scoalaDataSet.Clase);
eleviTableAdapter.Fill(scoalaDataSet.Elevi);
)

15. Acionai dublu click pe butonul terge, al formei FormDeleteElev. n metoda


de tratare introducei:

private void buttonl_Click(object sender, EventArgs e)


{
c l a s e T a b l e A d a p t e r l .Dele t e C l a s a (t e x t B o x l .T e x t ) ;
Close ();
)

16. Rulai cu F5.

La execuie vei constata c atunci cnd tergei o clas, se terg i toate rndurile
orfane din tabela Elevi, conform regulii de tergere n cascad pe care am impus-o
pentru meninerea integritii datelor la crearea constrngerii de cheie strin.
346 P artea a III - a. B aze de date

Tem de lucru:
Implementai facilitatea de tergere a unui elev, la selectarea opiunii terge
elev din meniul Elevi. Elevul va fi cutat dup cmpul id E le v .

Vederile u n e i b aze de date (Views)

Un View este o tabel virtual, compus din rezultatul unei interogri.


Vederile se creaz dinamic. Includ date selectate din una sau mai multe tabele ale
bazei de date, i eventual date rezultate n urma unui calcul.
Modificarea datelor n tabele duce automat la modificarea datelor afiate n
vederi. Au avantajul c nu ocup spaiu fizic pe disc.
Vederile se folosesc frecvent atunci cnd se dorete afiarea rezultatului
yo/n-ului tabelelor i cnd nu se dorete modificarea datelor ci doar vizualizarea lor.
Ne vom lmuri n cele ce urmeaz.

Aplicaia coala - adugarea vederilor

Vedere cu date selectate dintr-o singur tabel

S presupunem c vrem s vedem o tabel care conine numai coloanele


Diriginte i Clasa din tabela Clase. Nu este cazul s definim o tabel nou.
Construim o vedere care afieaz doar datele din aceste coloane. Procedai astfel:

1. Vederea va fi afiat ntr-un grid. Avem nevoie de o form nou. Adugai o


form nou proiectului, acionnd click dreapta n S o lu tio n E xplorer, alegei
Add i selectai Windows Form... Salvai clasa formei cu numele
FormViewDirigClasa.

2. Din T o o lb o x alegei un control DataGridview i plasai-l pe suprafaa formei.

3. n fereastra D atabase E xplorer, click dreapta pe itemul V iew s, apoi selectai


A dd New View.

4. In dialogul A d d Table, selectai tabela C la s e , apsai Add, apoi click pe


butonul Close.

5. n View Designer, selectai cmpul Diriginte pe diagrama clase, apoi


cmpul Clasa. Interogarea SELECT se genereaz n mod automat:
C apitolul 13. R elaii ntre tabele 347

dbo.V iew 3: Vi...A\5COALA.M DF)* dbo.Vie*2: Vi...A\SCOAtA.MpF)*

; :* (All Columns)
v Claia
I .MrElevi
j v j Diriginte

Output Sort Type

0
Column Alias

j Diriginte Clase

Clasa Clase 0

'.SELECT Diriginte, Clasa


FROM dbo.Clase

Apsai butonul Save, apoi introducei numele vederii: V ie w D ir ig c ia s e .

Avem o vedere, dar aceasta nu este nc integrat n dataset. Pentru aceasta,


deschidei D ataS et D e sig n e r cu dublu click pe itemul S c o a la D a ta S e t.x s d
n S o lu tio n E xp lo re r. Din panoul Database E xplorer, tragei cu ajutorul
mouse-ului vederea pe suprafaa designerului. Obinei:

S co a ia D a ta S e t.X sd * dbo.ViewOrig.,,LA\SCOALA,MDF) ' dbo.View2: Vi..,A\SCOALA.MDF)*


itebase Explorer ^ ^ X

3 / , J V v>. :'
j i Data Connections
ii coala.mdf IdElev
Clasa
4r _ J Database Diagram: ' NrEievi Nume
I J Tables Diriginte Media
t: J 3 Oase Clasa
+ I U Elevi *. Wr-ri *4SV f|
Views I f ti Fill.CetData () j &
i Q j ViewDirigClase. sau DeleteClasa (@Origiral_Oasa) p a FiB,GetData Q

3 Diriginte gy InsertClasa (fClasa,cg>lMrE!evi, (^Diriginte)


_U Clasa | J MaiEastaClasa (@Ca>a) VtewDirigClase
ti Stored Procedures
Diriginte
_ j Functions
? Clasa
*< Synonyms
r/rj sfo & g g g
'*' -J Types
> ' " i Assemblies fe Fil.GetDatan

8 n S o lu tio n E xplorer, dublu click pe forma vederii, pentru a deschide Form


Designer. Din fereastra Data Sources, tragei vederea pe suprafaa formei.

9. Acionai dublu click pe opiunea Diriginti-clase din meniul Rapoarte, aflat pe


F o rm l. n corpul metodei de tratare scriei:
348 P artea a III - a. B aze de date

private void dirigintiClaseToolStripMenuItem_Click(


object sender, EventArgs e)

FormCl a s e D i r i g fCIDir = n ew F o r m C l a s e D i r i g ();


fClDir.ShowDialogO;
}

10. Facei Build i rulai cu F5.

La rulare, n momentul n care selectai opiunea Diriginti-Clase, obinei:

Diriginte Clasa av I

H I ? IX
; Colcer X
: Vaida XI

: Berende ^XII
V
*
< >

Vedere cu date selectate din dou tabele

Aa cum am spus, tabela temporar rezultat n urma unui JOIN poate fi


afiat ntr-un View.
Ne ntoarcem la aplicaia coala. S presupunem ni se cere media pe clase.
Construim o vedere care afieaz clasa, dirigintele i media clasei. Avem nevoie
de informaii din ambele tabele, deoarece Diriginte este cmp n tabela clase,
iar Med i a (unui elev) este cmp n tabela Elev. Reamintim c ntre cele dou
tabele exist o constrngere de cheie strin, clasa este cheie strin n tabela
Elev. Procedai ca mai jos:

1. Adugai o form nou proiectului, cu numele F o rm V ie w M e d ia C la s e .

2. Din T o o lb o x alegei un control D a taGridView i plasai-l pe suprafaa formei.

3. n fereastra D atabase E xplorer, click dreapta pe itemul Views, apoi selectai


A dd New View.

4. n dialogul A dd Table, C la s e , adugai pe rnd ambele tabele cu ajutorul


butonului Add, apoi nchidei cu butonul C/ose.

5. n View Designer, selectnd opiunile din figura de mai jos, vei obine
interogarea necesar:
C apitolul 13. R elaii ntre tabele 349

i I* (All Columns) O * (AII Coums)


V j Clasa : r= J j lldEfev
ZjNrElevi l ( jN u m e
[Vj Diriginte - (f Media X
Clasa

<

Column Alias Table Output S... S... Group By Filter


Clasa Ciase 0 Group By
Diriginte Clase 0 Group By
Media MediaClasei Elevi 0 Avg

SELECT dbo,Clase.Clasa, dbo,Clase.Diriginte, VG(dbo,Elevi.Media) AS Mediadasei


, FROM dbo,Clase INNER JOIN
dbo.Elevi ON dbo.Clase.Clasa = dbo.Elevi,Clasa
(GROUP EftAtibo.Clase.Clasa, dbo,Clase.Diriginte

Evident, putei s completai i manual codul SQL. Observai c se face un


JOIN INTERIOR care returneaz cte un rnd pentru fiecare clas. Media
clasei se calculeaz cu funcia a v g () .

6. Apsai butonul Save, apoi introducei numele vederii: v ie w M e d ia C la s e .

7. Vederea trebuie inserat n dataset. Deschidei D ataS et D esigrter cu dublu


click pe itemul s c o a la D a ta S e t. x s d n S o lu tio n E xplorer. Din panoul
D atabase E xp lo re r, tragei cu ajutorul mouse-ului vederea pe suprafaa
designerului.

11. n S o lu tio n E xp lo re r, dublu click pe forma vederii, pentru a deschide Form


Designer. Din fereastra Data Sources, tragei noua vedere pe suprafaa formei
FormViewMediaCla.se.

12. Acionai dublu click pe opiunea Media pe clase din meniul Rapoarte, aflat pe
F o rm l. n corpul metodei de tratare scriei:

private void mediaPeClasaToolStripMenuItem_Click(


object sender, EventArgs e)

// Instantiem forma i o afim


FormViewMediaCIase fv = new FormViewMediaCIase();
fv.ShowDialog();

8. Rulai cu F5.
350 P artea a III - a. B aze de date

La execuie, dac selectai opiunea de meniu Media pe clase, obinei:

3 H M W F p
I Clasa Diriginte MediaCla sei A I
Vmescu j 9,989999
77111 l
;X ; Colcer 17,204933 92370 t
jXII IBerende : 7,75

* ! ! j V

< ' J >

Probleme propuse

1. Adugai aplicaiei coala un V iew care afieaz pe trei coloane: numele


diriginilor care au elevi cu medii peste o valoare introdus de la tastatur,
numrul de elevi din fiecare clas care ndeplinesc aceast restricie i clasa.

2. Creai o aplicaie care ntreine o baz de date cu numele Firm a. Baza de date
conine dou tabele: Clieni si Comenzi. Tabelele vor defini cel puin
urmtoarele coloane: Clieni: (IDCIient, Nume, Prenume, Telefon) si Comenzi:
(IDCIient, Data, ValoareComanda). Aplicaia va implementa operaii de
adugare de Clieni si de Comenzi. Va permite de asemenea afiarea tuturor
clienilor, iar pentru fiecare client, se va afia valoarea total a comenzilor
sale.

3. Implementai o aplicaie care s permit eliminarea dintr-o baz de date a


tuturor produselor care au preul cuprins ntre dou limite introduse de la
tastatur. Dac n baza de date nu exist nici o nregistrare cu proprietatea de
mai sus, s se afieze un mesaj. Pentru un produs se memoreaz: codul,
denumirea, preul, data recepiei.

4. S se realizeze o aplicaie care s permit manipularea unei baze de date care


conine un tabel cu structura: nume medicament, compensat sau nu, procent
compensare s i pre ntreg. Pentru aceast tabel s se poate actualiza preul
unui medicament localizat prin nume. S se realizeze o list cu medicamentele
care nu beneficiaz de compensare.
351

Bibliografie
[1] Ecma T e ch n ica l C om m ittee 39 Task G roup
C# Language Specification 4-th Edition, june 2006
[2] Jesse Liberty. Programming Cff. 2-nd Edition, O Reilly 2002.
[3] A n d re w Troelsen . Pro C# 2CC8 and the .Net 3.5 Platform. 4-th Edition.
Apress 2008.
[4] M ic ro s o ft MSDN E xpress L ib ra ry 2008

[5] Trey Nash. Accelerated C# 2Q08. Apress 2008


[6] S tanley Lippm an. C# P rim e r A Practical Approach. Pearson Education
Inc. 2003

[7] H erbert S childt. C# 2.0 The Complete Reference. 2-nd Edition


[8] D onis M arshall. Programming M icrosoft Visual C# 2005: The Language.
Microsoft Press 2006.
[9] Rob H arrop. Effective Data Access in C#. W rox Press 200
[10] Jam es H uddleston, Ranga Raghuram . Beginning C# 2005 Databases
from Novice to Professional. Apress 2006
[11] Paul K im m el. Advanced Cff programming. McGraw Hill/Osborne 2002
[12] John Sharp, Jon Jagger. Microsoft Visual C# .NET Step by Step.
Microsoft Press 2003
[13] F. S co tt Barker, Visual Cff 2005 Express Edition Starter Kit. Wiley
Publishing Inc. 2005
[14] M atthew MacDonald. Pro .. 2.0 Windows Forms and Custom
Controls. Apress, 2006.
[15] Jo h n Paul M ueller. Visual C if.N E T Developer's Handbook. SYBEX Inc.
2002
[16] Daniel S olis. Illustrated ft 2008. Apress 2008.
[17] M atthew M acDonald. Pro WPF in C# 2008: Windows Presentation
Foundation with .NET 3.5, Second Edition. Apress 2008
[18] Peter W rig h t. Beginning Visusf Cff 2005 Express Edition From Novice to
Professional. Apress 2006.
[19] MAHESH CHAND. A Programmer's Guide to ADO .NET in Cff. Apress
2003.
[20] M ickey W illiam s. Microsoft Visual Cff .NET. Microsoft Corporation 2002

S-ar putea să vă placă și