Documente Academic
Documente Profesional
Documente Cultură
Susana Gltan
9
Curs de
L& S info-m et
E d itu ra
L&S
INFO-MAT:
fp k
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: comenzi@ls-infomat.ro:
office@ls-infomat.ro:
http-.f/
CUPRINS
C# i platforma .NET...................................................................................7
.NET Framework........................................................................................................................8
Compilarea programelor pe platforma .NET........................................................................ 9
Instrumente de dezvoltare a aplicaiilor .NET.....................................................................10
Principalele caracteristici ale arhitecturii .NET...................................................................10
Mediul Integrat Visual C# 2008 Express Edition.....................................................................11
Instalare............................................................................................................................... 11
Compilare n linie de comand............................................................................................12
Primul program C #.............................................................................................................. 12
O scurt analiz a programului salut.cs................................................................................14
Crearea unei aplicaii de tip consol....................................................................................14
IntelliSense - o facilitate important a editorului de cod................................................... 16
Rezumatul capitolului............................................................................................................... 17
ntrebri i exerciii.................................................................................................................. 17
Limbajul C# . Introducere........................................................................18
Structura unui program simplu C # ...........................................................................................18
O aplicaie de tip Consol....................................................................................................18
Metoda M ain - punctul de intrare n aplicaie.....................................................................19
Calificarea complet a numelor cu ajutorul operatorului .................................................. 20
Parametri n linia de comand................................................................................................. 21
Variante ale metodei M ain.......................................................................................................23
Rezumatul capitolului...............................................................................................................24
ntrebri i exerciii..................................................................................................................24
........ 25
Tipuri.................................................
Tipuri predefinite.........................
Tipuri definite de programator.....
Tipuri valoare i tipuri referin....
Conversii ntre tipuri....................
Variabile i constante.......................
Enumerri..........................................
Expresii.............................................
Tablouri.............................................
Tablouri unidimensionale............
Tablouri multidimensionale.........
Tablouri neregulate......................
Instruciuni........................................
Instruciunea de selecie if ... else
Instruciunea de selecie s w itc h .
Ciclul f o r ...................................
Ciclul f o r e a c h ..........................
Ciclul w h i l e ...............................
Ciclul do w h i l e .......................
Instruciuni de salt necondiionat.
Spaii de nume..................................
Directive de preprocesare................
Directiva t d e f i n e ....................
Directiva tu n d e f i n e ...............
............ 25
............ 25
............ 27
............ 29
............ 31
............ 32
............ 33
............ 34
............ 36
............ 36
............ 38
............ 39
............ 42
............ 42
............ 43
.....44
.......... 44
..... 45
.......... 46
...........46
...... ...48
C# pentru liceu
Cuprins
Rezumatul capitolului..............................................................................................................53
ntrebri i exerciii................................................................................................................. 53
C#pentru liceu
Cuprins
Metode generice....................................................................................................................
Colecii.................................................................................................................................. - 19
Clasa generic S ta ck < T > ................................................................................................ 11?
Clasa generic L is t< T > .................................................................................................. 120
Clasa generic D ic tio n a ry C T k e y , T v a lu e > ..........................................................121
Tratarea excepiilor................................................................................................................. 123
Manevrarea stringurilor.......................................................................................................... 124
Operaii i metode.............................................................................................................. 125
Formatarea stringurilor...................................................................................................... 125
Transformarea stringurilor n valori numerice...................................................................126
Citirea unui ir de valori numerice.....................................................................................127
Citiri i afiri din fiiere de tip text....................................................................................... 128
Rezumatul capitolului............................................................................................................. 130
ntrebri i exerciii................................................................................................................ 130
C# pentru liceu
C aprins
Controlul ListView.................................................................................................................237
Controlul TreeView..................................................................
245
Controalele Web Browser i StatusStrip......................................
253
Integrarea WindowsMediaPlayer n aplicaii........................................................................ 257
XML cu C # ...............................................................................................270
Sintaxa XML.......................................................................................................................... 270
Clase .NET pentru Xml..........................................................................................................271
Citirea informaiilor dintr-un document XML....................................................................... 271
Descrcarea fiierelor XML de pe Internet............................................................................ 275
Citirea i analiza unui document XML cu XmlTextReader.................................................. 276
Crearea coninutului XML cu XmlTextWriter...................................................................... 279
Capitolul 1.
C# i platforma .NET
Partea I
Limbajul C#
Capitolul 1
C# i platforma .NET
Numele limbajului C# a fost inspirat din notaia t {diez) din muzic, care
indic faptul c nota muzical urmat de jf este mai nalt cu un semiton. Este o
similitudine cu numele limbajului C++, unde ++ reprezint att incrementarea unei
variabile cu valoarea 1, dar i faptul c C++ este mai mult dect limbajul C.
Limbajul C# a fost dezvoltat n cadrul Microsoft. Principalii creatori ai
limbajului sunt Anders Hejlsberg, Scott Wiltamuth i Peter Golde. Prima
implementare C# larg distribuit a fost lansat de ctre Microsoft ca parte a
iniiativei .NET n iulie 2000. Din acel moment, se poate vorbi despre o evoluie
spectaculoas. Mii de programatori de C, C++ i Java, au migrat cu uurin spre
C#, graie asemnrii acestor limbaje, dar mai ales calitilor noului limbaj. La
acest moment, C# i-a ctigat i atrage n continuare numeroi adepi, devenind
unul dintre cele mai utilizate limbaje din lume.
Creatorii C# au intenionat s nzestreze limbajul cu mai multe faciliti.
Succesul de care se bucur n prezent, confirm calitile sale:
Partea I. Limbajul C#
.NET Framework
Arhitectura .NET 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 Framework 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 interoperabilitatea limbajelor.
.NET este constituit din dou entiti importante:
Capitolul 1.
C# i platforma .N ET
10
Partea I. Limbajul C#
Capitolul 1.
C# i platforma .N ET
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 sistem pe care platforma este instalat.
Caracteristicilor de mai sus li se adaug i altele, care ies ns din cadrul
acestei lucrri.
Cerine de sistem
Sistemele de operare suportate sunt: Windows Server 2003, Windows Vista;
Windows XP.
>
>
Instalare
Visual C# 2008 Express Edition poate fi descrcat de pe site-ul Microsoft,
la 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 instalarea .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.
Partea I. Limbajul C#
12
Exist i versiunile Visual C# 2008 i Visual Studio 2008 cu faciliti suc imentare,
dar care nu sunt gratuite.
Ajuni n acest punct, dorim s atragem atenia asupra fptuit' 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 Kit (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.
Primul program C#
Este o tradiie pstrat n timp, ca o carte de programare s nceap cu
programul care afieaz pe ecran Salut lume ! . Vom compila i executa acest
program C# n linie de comand, urmnd paii de mai jos:
1.
{
Console.WriteLine("Salut lume!");
1
}
Capitolul 1.
C# i platforma .NET
13
Executarea programului
Rularea programului se face simplu, prin tastarea numelui fiierului .exe:
c:\teste>salut
Programul afieaz:
Salut lume!
C:\WINPOWS\sy5tein32tand.exe
C:Nteste>csc salut.es
[Microsoft <H> Uisual C# .NET Compiler uersiol
[for Microsoft <FO .NET Framework version 1.0|
[Copyright <C> Microsoft Corporation 2001. Al|
[C:Steste>salut
[Salut lume
14
Partea I. Limbajul C#
IMPORTANT!
O deosebire fa de C++ este faptul c trebuie s existe o clas, n cazul
de fa clasa Salut, care gzduiete metoda Main(). Aceasta, deoarece C# este
un limbaj p u r orientat obiect, i nu pot exista definiii de funcii n afara claselor
i nici variabile globale.________________________________ _____________
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.
Capitolul 1.
C# i platforma .NET
15
mm
Templates:
Visual Studio installed templates
rs!)
Windows
Forms A...
Class Library
ra*t
i #1
1 d*l
WPF
Application
WPF Browser
Application
cttj
HP
Empty Project
My Templates
Search Online
Templates...
salut
Cancel
Solution
Explorer
Solution Explorer - salut
sL& aa
S
Program.es
start Page
1using System;
U 3 i n g System.Collections.Generic;
using System.Linq;
-U3ing System.Text;
0 namespace salut
|{
class Program
{
static void Hain(stringf] args)
{
ij-
L>
>
>
........ ,
4 X
Partea I. Limbajul C#
16
4.
5. Rularea programului.
Programul este gata de compilare i rulare. Se apas F5 ori click pe iconul ^
{
static void Hain(string[]
args)
{
Con 3 o le .WriteLine ('*mi place CU
^ OpenStandardOutput
o ut
OutputEncoding
v Read
v ReadKey
string Console.ReadLineQ
Reads the next line of characters from the standard input stream.
v ReferenceEquals
v SetBufferSize
v SetCursorPosition
Exceptions:
System.10 .IOException
5ystem.OutOf MemoryException
System.ArgumentOutOfRangeException
Capitolul 1.
C# i platforma .NET
17
Rezumatul capitolului
ntrebri i exerciii
1.
2.
3.
4.
Ce este un assembly ?
5.
18
Partea I. Limbajul C#
Capitolul 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, motenire
i polimorfism.
Clasele C# conin cmpuri i proprieti care rein informaii despre obiecte
i metode (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 evenimentelor.
Vom reveni pe larg asupra tuturor acestor concepte n capitolele urmtoare.
C# admite programarea 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
collector (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.
Capitolul 2.
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);
}
}
}
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 ( /*
( / / ), ntocmai ca C++.
...
20
Partea I. Limbajul C=
Clase
C# lucreaz cu clase. Fiind un limbaj pur -jnientat aonec:, nu putei scrie un
program C#fr clase. Totul se petrece r -tenatail anse"
ceea ce aparine
unei clase, va fi definit n interiorul ei. Nu r sut aifiiaitalie z coaie i nici funcii
globale. Un program trebuie s aib cel puin c ::sse aceea : ='e conine metoda
Main. O clas se definete cu ajutorul cuvn:_ . oho* c l u ;
Exemplu:
class Persoana
{
// membrii clasei
}
Observaie:
Programatorii C++ trebuie s fie avizai de faptu: c n C- dup ultima
parantez nchis a clasei, nu se pune ; .
Exemple:
Capitolul 2.
2.
21
directiva using
class Test
1
static void Main()
{
Console.WriteLine("C#");
}
}
// Al doilea program precizeaz calea complet
// a numelui metodei
class Test
{
static void Main()
{
System.Console.WriteLine("C#");
}
}
{
for (int i = 0; i < args.Length; i++)
Console.Write(args[i] + " ");
Partea I. Limbajul C#
22
Program.es
Start Page
Application
Build
a b c d e
Build Events
Debug*
Working directory:
i
Resources
........................................................ - r c i
Settings
Capitolul 2.
23
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
> C# este case-sensitive. Aceasta nseamn c Main este corect, iar main greit, c
WriteLine nu este tot una cu writeline.
>
Cuvintele cheie din C#, (return, int, void, if, etc) se scriu cu litere mici.
>
Partea I. Limbajul C#
24
Rezumatul capitolului
Main.
Main are cteva versiuni. Prin tabloul de stringuri pe care Main l are ca
ntrebri i exerciii
1.
2.
3.
4.
5.
Capitolul 3.
Fundamentele limbajului 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.
Tipurile sistem 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
9 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,
n 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 spaiui 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. Xnt32 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.
26
Partea I. Limbajul C#
Tipul object
Tipul object este rdcina ntregii ierarhii de tipuri i clasa de baz a
tuturor claselor din .NET Framework. 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.
Tipul string
Tipul string 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).
Tabelul 3.1
Tip
Tipuri C# predefinite
Dimensiune
Tip .Net
asociat
(bytes)
object
string
byte
char
bool
sbyte
short
ushort
int
variabil
variabil
1
2
1
1
2
2
4
Object
String
Byte
Char
Boolean
SByte
inti 6
UIntl6
Int32
uint
float
4
4
Uint32
Single
double
Double
decimal
12
Decimal
long
ulong
8
8
Xnt64
UInt64
Descriere
Tipul de baz al tuturor tipurilor
Tip ir de caractere.
Tip ntreg fr semn. [0, 255]
Tip caracter. Reine carcatere Unicode
Valori true sau false
Tip ntreg cu semn. [-128,127]
Tip ntreg cu semn. [-32768,32767]
Tip ntreg fr semn. [0, 65535]
Tip ntreg cu semn.
[-2.147.483.648, 2.147.483.647]
Tip ntreg fr semn. [0, 4.294.967.295]
Tip real cu virgul mobil, simpl precizie.
Valori cuprinse ntre +/-1,5 x 10"45 i +/-3,4
x 1038 cu 7 cifre semnificative
Tip real cu virgul mobil, dubl precizie.
Valori cuprinse ntre +/-5,0 x IO'324 i +/-1,8
x IO308 cu 15 cifre semnificative
Tip zecimal cu virgul fix. Precizie de cel
puin 28 cifre semnificative.
Tip ntreg cu semn.
[-263, 263 - 1]
Tip ntreg fr semn. [0, 264]
Declarri de variabile
Toate declarrile de mai jos sunt legale:
object ol, o2 = nuli;
string s = "Salut";
sbyte b = 6;
short h = 13;
Capitolul 3.
Fundamentele limbajului 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, f2 = 3.8F;
double dl = 1.3, d2 = 0.2D;
char c = 'T ';
Decimal d = 12. 4M;
/ / Mdesemneaz o constant decimal
un tip user-defined.
Tipul class
n C# clasele se creeaz cu ajutorul cuvntului cheie class:
class nvme_clasa
{
modificator_acces Tip nume_membru;
I I ali membri
}
Exemplu:
class ntreg
{
public int x;
De reinut:
Partea I. Limbajul C#
28
IMPORTANT
Accesarea membrilor clasei se face cu sintaxa: referina.membru
l
static void Main()
{
ntreg r = new ntreg();
r.x = 10;
// Atribuie valoarea 10 cmpului x
Console.Write(r.x);
// Afieaz 10
}
}
Observai c un program C# poate s conin una sau mai multe clase, dintre care
una singur conine metoda Main.
Structuri
Structurile se construiesc prin utilizarea cuvntului cheie struct. Au fost
introduse n C# pentru a permite programatorului s defineasc tipuri valoare. Sunt
similare claselor, dar le lipsesc unele caracteristici, cum ar fi motenirea. Obiectele
de tip struct se depoziteaz n stiv. Se creeaz i se acceseaz mai rapid
dect cele alocate dinamic. Sunt de preferat atunci cnd avei nevoie de obiecte
mici ca dimensiuni, sau care se construiesc ntr-un ciclu.
Sintaxa este similar cu cea a claselor:
Exemplu
using System;
struct Persoana
{
public string nume;
public int vrsta;
}
Capitolul 3.
Fundamentele limbajului C#
29
class TestStruct
{
static void Main()
{
// Datele obiectului p se memoreaz n stiv
Persoana p = new Persoana();
p.nume = "Iulia";
p.varsta = 8;
Console.Write("Numele {0}\nVarsta {1} ani",
p.nume, p.varsta);
}
}
Not
IMPORTANT
Tipurile valoare difer de tipurile referin prin faptul c variabilele de
tip valoare conin datele obiectului, n timp ce variabilele de tip referin conin
referine la obiecte.
Pentru a lmuri aceasta, vom analiza programul:
Partea I. Limbajul C#
30
class C
{
}
// Tip referin
struct S
// Tip valoare
{
}
class StackHeap
{
static void Main(string[] args)
{
int x = 7;
// Variabil local.
S s = new S(); // s - variabil local
C r;
r = new C();
}
}
Capitolul 3.
Fundamentele limbajului C#
31
DE RETINUT:
j
>
>
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:
short a = 4;
int n = a;
// Conversie implicit spre tipul int.
// Nu se pierde informaie
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;
short s2 = (short)n;
// Incorect. Nu va compila
// Corect. Conversie explicit
// cu pierdere de informaie
32
Partea I. Limbajul C#
f = b;
b = f;
ulong e = -3;
a = c;
c = a;
c = (char)a;
/ / Corect. Conversie ia p L ic ^ r a
//
//
//
//
//
Eroare.
Eroare.
Corect. Conversie implici*
Eroare.
Corect. Conversie explicic
Variabile i constante
Variabile
O variabil este o locaie de memorie care are un tip asociat. n programul
de mai jos, a i b sunt variabile:
using System;
static void Main(string[] args)
{
int a = 2;
int b;
b = 3;
System.Console.WriteLine(a + " " + b ) ;
>
Programul afieaz: 2 3
Comentai instruciunea b = 3; Vei constata faptul c programul are o eroare.
Compilatorul anun c ai ncercat s utilizai o variabil creia nu i-a fost atribuit
o valoare.
IMPORTANT
C# nu permite utilizarea variabilelor crora programul nu le-a asociat anterior o
valoare.
Constante
O constant este o variabil iniializat, a crei valoare nu mai poate fi
modificat n program. Constantele se introduc cu ajutorul calificativului const:
using System;
static void Main (stringH args)
{
const long x = 100; // Corect
const string s;
// Eroare. Constanta neinitializata
s = "Salut";
System.Console.WriteLine (x + " " + s);
}
Capitolul 3.
Fundamentele limbajului C#
33
Enumerri
Enumerrile sunt tipuri de date de tip valoare, create de programator n
scopul de a grupa sub un nume un set de constante simbolice.
Exemplul 1:
using System;
enum Saptamana
{
Luni, Marti, Miercuri, Joi,
Vineri, Sambata, Duminica
}
class TestEnum
{
static void M a i n ()
{
Saptamana ziua = Saptamana.Luni;
if ( ziua == Saptamana.Luni)
Console.Write("Luni e {0} Marti e {1}",
(int)Saptamana.Luni, (int) Saptamana.Marti);
}
}
Programul afieaz: Luni e 0 Marti e 1
De retinut:
i
Exemplul 2
Membrilor unei enumerri li se pot asocia valori de tip ntreg:
using System;
enum Note
{
Mate = 10,
Info = 9,
Romana = 8
Partea I. Limbajul C#
34
class TestEnum
{
static void Main()
{
Console.Write("mate: {0}\ninfo: {1}\nromana: {2}",
(int)Note.Mate, (int)Note.info, (int)Note.Romana);
}
}
Programul afieaz:
mate: 10
info: 9
romana: 8
Expresii
Expresiile n C# sunt similare cu expresiile din C++ i Java. Expresiile se
construiesc folosind operanzi i operatori i n general ntorc o: valoare n urma
evalurii lor. Operanzii sunt variabile de memorie, nume de metode, de tablouri, de
obiecte, etc.
Tabelul de mai jos prezint operatorii C# n ordinea descreterii precedenei
(prioritii) lor.
Tabelul 3.3. Operatorii C#
Grupul de
operatori
__ .
Operator
0
[]
++
Multiplicativi
f (X)
Apel de metod
Acces la elem. tablourilor
Postincrementare
Postdecrementare
Creare de obiecte
Creare de tablouri
Informaii despre tipul T
Evaleaz expresia x n
medii checked i
unchecked
Identitate i negaie
Negaie logic
Negaie pe bii
Preincrementare
Predecrementare
Conversie explicit
nmulire, imprire,
modulo
typeof
X++
checked
unchecked
~
++
0
* / %
Descriere
x .m
a [x]
new
Unari
Expresii
n e w T(x)
n e w T[x]
typeof(T)
c h e c k e d (x)
u n c h e c k e d (x)
+x
-x
!x
~x
++X
- -X
(T) x
x*y
x/y
x%y
Capitolul 3.
x+y
x-y
x
x
y
y
<
Relaionali i
de testare a
tipului
II
A
II
V A V
V A
Aditivi
Shiftare
Fundamentele limbajului C#
is
x is T
as
x as T
35
Adunare, scdere
Deplasare pe bii la stnga
i la dreapta
Operatori aritmetici
true,
dac x este
convertibil la T. Altfel,
false
!=
x == y
&
x
x
| y
&& y
II
II y
?:
? y
x %= y
ii
ii
x = y
etc.
: z
<
II A
+ A
/=
*=
>t
I
&&
x != y
& y
II V II
<*> v
Atribuire
==
<
Egalitate
AND logic
XOR logic
OR logic
AND
condiional
OR
condiional
Condiional
Retumeaz x convertit la
T sau n u l i dac
conversia e imposibil
Egal i diferit
AND logic pe bii
XOR logic pe bii
OR logic pe bii
Evalueaz y numai dac x
este t r u e
Evalueaz y numai dac x
este f a l s e
Evalueaz y dac x este
true. Altfel, evalueaz z
Atribuire
simpl
i
atribuiri compuse
Observaie:
Partea I. Limbajul C#
36
Tablouri
Un tablou este o structur de date coninnd variabile de acelai tip. n C#
tablourile sunt tipuri referin. Tablourile pot fi unidimensionale sau
multidimensionale. Cele multidimensionale, la rndul lor pot fi dreptunghiulare
sau neregulate (jagged).
Tablouri unidimensionale
Declararea tablourilor unidimensionale se face preciznd un tip de dat
urmat de operatorul de indexare i numele tabloului. Crearea tabloului se face cu
new urmat de tip i dimesiunea tabloului cuprins ntre paranteze ptrate.
Declarare: Tip[] a;
Creare:
a = new Tip[n] ;
Tablourile se indexeaz de la 0. Un tablou cu n elemente este indexat de la 0 la n1.
Exemplul 1:
Programul de mai jos definete un tablou cu 5 valori de tip int.
using System;
class TabUnidiml
{
static void Main()
{
// Tablou cu 5 elemente de tip int
int[] a;
// Declarare
a = new int[5]; // Creare
for (int i = 0; i < a.Length; i++)
a [i] = i + 1;
for (int i = 0; i < a.Length; i++)
Console.Write("a[{0} ] = {l}\n", i, a[i]);
}
Programul afieaz:
a[0]
a[l]
a [2]
a[3]
a [4]
=
=
=
=
=
1
2
3
4
5
Capitolul 3.
IMPORTANT !
Fundamentele limbajului C#
37
_________________ ____________________
Exemplul 2:
Mai jos, a, b, c, sunt tablouri de double, char, string, respectiv obiecte
de tip A.
class TabUnidim2
{
class A
{
}
static void Main{)
/
}
}
Programul afieaz:
null null null null null null null 0 0 0 0 0 0 0 0 0 0
Observaii:
9
1.
2.
Initialializare
9
Partea I. Limbajul C#
38
Exemple:
// Tablou cu 4 elemente.
int[] a = new int[] | 7, 4, 3, 0 );
// Sintax alternativ. Tablou cu 3 elemente
int[]
b = {10, 2, 17};
float[] c = { 1.2F, 7.9F, -8F };
string[] sl = new string[]
Tablouri multidimensionale
Un tablou poate avea una, dou sau mai multe dimensiuni.
Exemple:
// Tablou bidimensional cu 3 linii i 5 coloane
doublet,] a = new double[3, 5];
// Tablou tridimensional cu dimensiunile 3, 7 i 5
doublet, ,] a = new double[3, 7, 5];
Accesarea elementelor
Accesarea elementelor unui tablou multidimensional se face cu sintaxa
cunoscut din limbajul Pascal. De exemplu, elementul aflat pe linia 2 i coloana 0
ntr-o matrice se acceseaz astfel: a [2, 0].
Iniializare
DE RETINUT
Dac ai creat mai nti referina, iar tabloul va fi creat ulterior, atunci sintaxa
alternativ de iniializare nu se mai poate folosi. n acest caz este obligatorie
utilizarea operatorului new.
Capitolul 3.
Fundamentele limbajului C#
39
Exemplu:
using System;
class TabBidim
{
static void Main()
{
int[,] y;
// y = { { 1, 2, 3 }, { 2, 3, 0 } };
i n t [, ] x ;
x = new int[,] { { 1 , 2 , 3 } ,
// Ilegal
{2,3,0}
} ; / / OK
{
for (int j = 0; j < 3; j++)
Console.Write(x[i, j] + " ");
Console.WriteLine();
}
}
}
Ieire:
12 3
2 3 0
Tablouri neregulate
Un tablou neregulat (jagged array) este un tablou ale crui elemente sunt
tablouri. Elementele pot fi tablouri unidimensionale sau chiar multidimensionale.
Exemplu:
Un jagged array cu dou elemente, fiecare dintre acestea fiind un ir de
int, se declar astfel:
int[][] a = new int [2][];
Iniializare
Partea I. Limbajul C#
40
1.
=new int[]
=new int[]
= new int[]
{ 2, 7, 3, 8 };
{ 0, -1 };
{ 1, 9, 4 };
-1
2.
{
new int[]
new int[]
new int[]
{1, 4 },
{5, 9, 0, 7,
{6, 8, 3 }
2 },
};
3. A treia variant de iniializare este:
int[] [] a =
{
new in t[]
new int[]
new int[]
{1, 4 },
{5, 9, 0, 7,
{6, 8, 3 }
2 },
};
4. Cu ajutorul cuvntului cheie var, se pot iniializa att variabile simple ct i
};
n fiecare caz compilatorul deduce tipul de dat din tipul constantelor de iniializare.
Capitolul 3.
Fundamentele limbajului C#
41
Accesarea elementelor
Pentru un tablou neregulat ale crui elemente sunt tablouri unidimensionale,
accesarea se face la fel ca la tablourile din C++: a [ i ] [ j ] .
Exemplu:
using System;
class JaggedArray
{
static void Main()
{
int[] [] a =
{
new in t[] { 1, 4 >,
new in t[] { 5, 9, 0, 7, 2 },
new int[] { 6, 8, 3 }
>;
for (int i = 0; i < a.Length; i++)
{
for (int j = 0 ; j < a[i].Length; j++)
Console.Write(a[i][ j ] + " ");
Console.WriteLine();
}
}
}
Ieire:
1 4
5 9 0 7 2
6 8 3
Exemplu:
Elementele tabloului neregulat a sunt tablouri dreptunghiulare de valori int:
int[] [,] a = new i nt [3] [,]
{
new
new
new
};
7}, {5, 0} },
12} },
9}, {0, 6},
{3, -1} }
Partea I. Limbajul C#
42
Instruciuni
t
n C# o declarare (statement) poate fi: o expresie, o instruciune simpl, o
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
local.
Un program C# este o secven de asemenea statements care se evalueaz
n ordine. n continuare, vom folosi cuvntul instruciune pentru statement. Fiecare
intruciune se termin cu ;. Intruciunile C# sunt preluate cu unele mici modificri
din C i C++. n continuare vom prezenta intruciunile care controleaz fluxul de
execuie al programului.
Instruciunea
de selecie
if ... else
Instruciunea i f . ..else este mprumutat din limbajul C. Controleaz
fluxul programului prin evaluarea unei expresii booleane. n funcie de valoarea de
adevr, selecteaz pentru executare o secven de instruciuni sau o alta.
if (e x p r e s i e _ b o o l e a n )
instruciuneal;
else
instruciunea2;
sau
if (e x p r e s i e _ b o o l e a n )
{
bloc_instructiunil;
}
else
{
bloc_instructiuni2;
}
Exemplu:
string s = Console.ReadLine();
int x = int.Parse (s) ;
if ( x >= 0 )
Console.Write("pozitiv");
else
Console.Write("negativ");
Capitolul 3.
Fundamentele limbajului C#
43
else
i n t r u c i u n e 2 ; // se asociaz cu if
(e x p r e s i e 2 )
De retinut:
1.
Instruciunea
de selecie
switch
Instruciunile i f imbricate sunt greu de scris corect, greu de citit i greu de
depanat, switch este o intruciune de control mai potrivit atunci cnd avei un set
complex de alegeri de fcut. Sintaxa este identic cu cea din C++.
Sintaxa:
s w itc h
{
( n )
case v a l l : b l o c _ i n s t r u c i u n i l ;
break;
case val2: b l o c _ i n s t r u c i u n i ;
break;
// alte cazuri
default: b l o c _ i n s t r u c i u n i ;
// opional
}
n este o variabil de tip ntreg, de tip char sau de tip string, vall, val2, ... etc,
sunt valorile pe care le poate lua n. Controlul este transferat etichetei case care
potrivete valorii lui n.
Partea I. Limbajul C#
44
int k = O;
switch ( k )
{
case O :
Console.WriteLine ( "cazul 0" );
// goto case 1;
case 1:
case 2:
Console.WriteLine( "cazul 1 si 2" );
break;
}
Cderea prin ramuri se poate face numai pentru cazuri vide, cum e case 1. Dac
dorii un salt direct la o anume etichet, folosii instruciunea de salt necondiionat
goto. Dac scoatei de sub comentariu goto case 1; n secvena de program
precedent, atunci pe ecran se va afia:
cazul 0
cazul 1 si 2
Ciclul f o r
Este o instruciune identic cu cea din C++.
Sintaxa:
for (e x p r e s i e i ; expresie2; expresie3)
{
bloc_instructiuni;
>
Dac bloc_instruciuni e format din o singur instruciune, atunci acoladele
sunt opionale. Se evalueaz mai nti expresiei. Apoi se evalueaz
expresie2. Aceasta controleaz bucla. Dac expresie2 este evaluat true, se
execut instruciunile cuprinse ntre acolade, apoi expresie3. Se reia evaluarea
expresie2 i ciclul continu pn cnd expresie2 este evaluat false. Apoi
controlul este cedat instruciunii urmtoare ciclului for.
Toate expresiile sunt opionale. Dac expresie2 lipsete, condiia de test
este evaluat true:
for( ;; )
Console.Write("Ciclu infinit !");
Ciclul fo re a c h
foreach este nou n familia de limbaje C. Este folosit pentru iterarea printre
elementele unui tablou sau ale unei colecii. Coleciile sunt containere de tip
generic, care pot reine secvene omogene de obiecte, aa cum vom vedea mai
trziu.
Capitolul 3.
Fundamentele limbajului C#
45
Sintaxa:
foreach (Tip identificator in expresie)
bloc_instruciuni;
Exemplu:
using System;
class TestForeach
{
static void Main()
{
in t [] a = {10, 20, 30};
foreach (int x in a)
Console.Write(x + " ");
Console.WriteLine() ;
string[] st = { "UNU", "DOI", "TREI" };
foreach (string s in st)
Console.Write(s + " ");
}
}
Ieire:
10 20 30
UNU DOI TREI
Ciclul w h ile
Este mprumutat fr modificri din C++.
Sintaxa:
while (e x p r e s i e )
{
bloc_instruciuni;
}
Dac bloc_instruciuni e format dintr-o o singur instruciune, atunci
acoladele sunt opionale. Se evalueaz expresie. Dac este evaluat true,
atunci se execut bloc_instruciuni. Se reia evaluarea expresiei. Ciclul
continu ct timp este evaluat true.
Exemplu:
Partea I. Limbajul C#
46
int x = 5 ;
while ( x > O )
x ;
Ciclul do 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
{
bloc_instruciuni;
} while (e x p r e s i e );
Observaie
Rezultatul evalurii expresiilor care controleaz buclele C# trebuie s fie o
valoare boolean, adic true sau false. Secvena urmtoare nu va compila:
int x = 5;
do
{
x;
} while ( x );
Instruciuni
de salt necondiionat
f
Instruciunea goto
Utilizarea goto este nerecomandabil, deoarece produce cod greu de
neles (cod spaghetti). n cazul n care dorii totui s o folosii urmai paii:
1.
2.
Capitolul 3.
Fundamentele limbajului C#
47
Exemplu:
using System;
public class GoTo
{
static void Main()
{
int x = 1;
repeta:
// Eticheta
Console.Write( x + " ");
X ++ /
if (x <= 5)
' goto repeta; // Salt la eticheta
}
}
Ieire:
1 2 3 4 5
Exemplu:
using System;
public.class TestBreakContinue
{
static void Main()
{
for (int i = l;i 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:
0 2 4 6 8 10
Partea I. Limbajul C#
48
Sugestie
Nu este indicat s utilizai intens aceste instruciuni, deoarece creeaz puncte
multiple de ieire din cicluri, ceea ce duce la cod dificil de neles i de ntreinut
(cod spaghetti).
Spaii de nume
n capitolele 2 i 3 s-au discutat primele noiuni referitoare la spaii de nume
(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
utilizarea bibliotecilor de clase, dar i pentru organizarea i sistematizarea tipurilor
de date. De exemplu, dac ntr-o aplicaie utilizai dou biblioteci neprotejate prin
spaii de nume, care provin de la furnizori diferii, este posibil ca un acelai nume
de clas, s-i spunem Button, s fie definit n ambele biblioteci, ceea ce ar crea o
coliziune n program, inacceptabil de ctre compilator.
ntreaga^ Biblioteca de Clase .NET se gsete n interiorul acestor
namespaces. n afara spaiilor de nume ale bibliptecii .NET Framework sau ale
bibliotecilor altor furnizori, C# v permite s v creai propriile spaii de nume. Se
definesc foarte simplu cu ajutorul cuvntului cheie namespace.
Exemplu:
namespace MySpace
{
static void Main()
{
}
}
}
namespace Z
{
namespace W
{
}
}
static void Main()
{
}
}
Capitolul 3.
Fundamentele limbajului C#
49
System
Windows
Forms
clasa
Button
{
static void M a i n ()
{
System.Windows.Forms.Button b =
new System.Windows.Forms.Button();
}
}
Partea I. Limbajul C#
50
{
Button b = new Button();
}
}
Not:
Pentru ca programul de la punctul b) s compileze, trebuie s aducei
proiectului de tip consol o referin, la spaiul de nume System. Windows.Forms
astfel:
n Solution Explorer, click dreapta pe numele proiectului.
Alegei Add reference.
n tab-sheet-u l .Net alegei System.Windows.Forms i apsai OK.
ATENTIE
!
j
{
static void Main()
{
Windows.Forms.Button b = new Windows.Forms.Button();
}
}
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:
System.Windows.Forms.Button b =
new System.Windows.Forms.Button();
Alias-uri
Pentru simplificarea scrierii putei declara nume alternative pentru spaiile de
nume, astfel:
Capitolul 3.
Fundamentele limbajului C#
51
// Creeaz un alias N
namespace NI
{
namespace N2
{
namespace N3
{
public class C { }
}
}
}
public class estAlias
{
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 estAlias
{
static void Main()
{
F .ComboBox cb = new F .ComboBox();
}
}
Directive de preprocesare
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 du
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 build final a unei aplicaii, nu dorii s mai compilai poriuni de cod pe
care l-ai folosit pentru depanare.
Partea I. Limbajul C#
52
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
// Cod neafectat de preprocesor
Capitolul 3.
Fundamentele limbajului C#
53
Rezumatul capitolului
n tre b ri i e x e rc iii
1.
5.
6.
54
Partea I. Limbajul C#
Capitolul 4
Obiecte i clase
Limbajul C# este un limbaj orientat-obiect. Limbajele orientate pe obiecte au
calitatea c permit programatorului s-i creeze noi tipuri complexe de date.
Tipurile se obin prin definirea de clase. Clasele sunt baza programrii orientat pe
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
numete instaniere. Obiectul creat se numete instan a clasei.
Diferena dintre un obiect i o clas este aceeai ca diferena ntre o pisic i
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
obiectele din realitate, dar i obiecte abstracte.
O clas Pisica, specific trsturile care ne intereseaz la o pisic: nume,
ras, greutate, culoarea blnii, etc. De asemenea, clasa descrie aciunile pe care o
pisic le poate face: s sar, s zgrie, s toarc, etc. Pisica Kitty, rasa Birmanez,
greutatea - 4 Kg, culoarea blnii - gri, este o instan a clasei, deci un obiect de tip
Pisica.
Capitolul 4.
55
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 interfaa 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. Reutilizarea codului 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,
Partea I. Limbajul C#
56
Clasele
C#
n afara celor cincisprezece tipuri predefinite n C#, putei crea propriile tipuri
de date (user-defined types). Exist ase categorii de tipuri pe care le putei crea:
1. Tipuri class
2. Tipuri struct
3. Tipuri tablou
4. Tipuri enum
5. Tipuri delegate
6. Tipuri interface
Odat ce ai definit un tip de dat l putei utiliza ca i cnd ar fi un tip predefinit.
Dintre tipurile enumerate mai sus, class este cel mai important. O clas
este o structur de date care poate depozita date i executa cod. 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 funcii care opereaz cu aceste
date.
Caracterisiticile obiectului se memoreaz n cmpurile clasei.
Capabilitile, aciunile obiectului, se codific n metodele clasei.
Cmpurile i metodele unei clase se numesc membrii clasei. 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:
Date membre
Cmpuri
Constante
Funcii membre
Metode
Proprieti
Constructori
Capitolul 4.
57
Destructori
Operatori
Indexatori
Evenimente
Definirea claselor
O clas se declar cu ajutorul cuvntului cheie class.
Sintaxa minimal:
class nume__clas
{
// Cmpuri
[modificator de acces]
Tip n u m e ;
II Metode
[modificator de acces]
TipRetur N u m e M e t o d ( P a r a m e t r i ) ;
}
Modificatorii de acces controleaz regiunile programului care pot accesa membrii
clasei. Tabelul descrie cele ase tipuri de modificatori:
Atributul
public
private
protected
internal
protected internal
Descriere
Acces nelimitat
Acces limitat la propria clas
Acces limitat la propria clas i la clasele derivate
Acces limitat la programul care conine clasa
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.
}
2.
Partea I. Limbajul C#
58
Exemplul 1:
class Program
{
static void Main()
{
}
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.
Exemplul 2:
class Test
{
int x = 100;
// Cmp privat
{
x = 10;
Test r;
r = new Test () ;
r.x = 20;
//
//
//
//
//
//
}
Exemplul 3:
using System;
class Test
t
private int x;
// Metode publice
public int GetX()
{
return x;
// Cmp privat
Capitolul 4.
59
{
x = n;
}
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);
// Corect. SetX() este public
Console.WriteLine (r,.GetX () ) ;
}
}
Ieire: 10
Programul de mai sus are dou clase. n clasa Program, metoda Main(),
creaz un obiect de tip Test, care mai apoi este utilizat pentru accesarea
membrilor si publici.
t
// codul metodei
}
Apelul unei metode:
NumeMetod (ListaArgumente ) ;
Partea I. Limbajul C#
60
{
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; II a, b - variabile locale
// a, b - argumente pasate prin valoare
s.Schimba(a, 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
transmiterea prin valoare x i y sunt copii locale ale argumentelor a i b.
Argumentele nu trebuie s fie n mod obligatoriu variabile. Poate fi argument orice
expresie care se evalueaz la tipul parametrului formal.
Parametri referin
i
Capitolul 4.
61
{
int aux;
aux = x; x = y; y = aux;
}
int a = 10, b = 20;
s .Schimba(ref a, ref b ) ;
//s.Schimba(2*a, b - 1); //
//
Rulai programul. Va afia: a = 20,
// Iniializare obligatorie
// Apel
Greit! Argumentele nu
sunt variabile de memorie
b = 10
3arametri de ieire
Parametri de ieire sunt utilizai pentru a transmite date din interiorul metodei
ap 'e codul care a apelat-o. Nu conteaz valorile iniiale ale argumentelor, ci doar
ne e finale.
lerine:
>
>
Exemplu:
sLass OutParam
public void Metoda(out int x)
{
// int y = x; // Eroare!
x = 100;
// Iniializare nainte de
x++;
// a se citi din variabila x
Partea I. Limbajul C#
62
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.
Parametrii de ieire au urmtoarele caracteristici:
n interiorul metodei, parametrilor de ieire trebuie s li se atribuie valori
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.
Tuturor parametrilor de ieire trebuie s le fie atribuie valori nainte de
revenirea din apel.
Parametri tablou
Parametrii tablou (parameter array) admit zero sau mai muli parametri
actuali pentru un acelai parametru formal.
Restricii:
*
Exemplu:
class Params
{
public void Print(params int[] x)
{
foreach (int i in x)
System.Console.Write(i + " ");
System.Console.WriteLine();
}
}
Capitolul 4.
63
class Program
{
static void Main(string[] args)
{
// 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.
Suprancrcarea metodelor
C# suport suprancrcarea metodelor clasei (overloading). 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 O v e rlo a d in g dorim s suprancrcm metoda: v o id F ( i n t a)
c la s s O v e rlo a d in g
{
v o id F ( i n t a) { }
v o id F (c h a r b) { }
v o id F ( i n t a, ch a r b) { }
v o id F ( i n t a, i n t b) { >
/ / i n t F ( i n t a ) {}
}
{}
/ / C o re ct
/ / C o re ct
/ / C o re ct
/ / G r e it! Tipul parametrului
// formal este acelai
Partea I. Limbajul C#
64
}
Accesarea acestor membri se face prin numele clasei, astfel; C .x i c . F ( ) ;
Exemplul 1:
class Program
{
static int x = 10;
static void F()
{
}
int y = 20;
void G()
// Membri ne-statici
{
}
static void Main(string[] args)
{
// Membrii statici aparin clasei
x = 100;
// Corect
F();
// Corect
Program.x= 100; // Corect! Accesare prin
Program.F();
// numele clasei.
//
//
Capitolul 4.
65
Observaie:
C#admite iniializarea datelor membre, la momentul declarrii lor, aa ca
mai sus: int y = 20; sau int x = 10;
Exemplul 2:
Cnd accesai membrii statici din afara clasei trebuie s folosii sintaxa:
NumeClas.MembruStatic;
class ClasaMea
{
public static string s = "Ionel";
public static void F() { }
}
class Test
{
static void Main(string[] args)
{
//
//
s = "Marcel";
// Greit
ClasaMea.s = "Marcel"; // Corect
F ();
// Greit
ClasaMea.F ();
// Corect
}
}
Constante
Dac dorii s pstrai valori care nu se vor schimba pe parcursul execuiei
programului i n acest scop vrei s le protejai la scriere, vei declara constante. n
C# , constantele apar n dou forme:
1.
2.
Constante locale.
Constante membre ale clasei.
{
const int x = 100;
// Iniializare obligatorie
// x++
// Eroare!
a = x;
// Corect
}
Constantele membre se comport la fel ca valorile statice. Sunt vizibile n fiecare
instan (obiect) al clasei i sunt disponibile chiar n lipsa obiectelor clasei.
Exemplu:
Partea I. Limbajul C#
66
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 statici:
NvmeClas.NumeConstant.
Constructori
Constructorul de instan este o metod special a clasei, care are rolul de
a creea, a construi obiecte. O clas are cel puin un constructor. De fiecare dat
cnd instaniai un obiect de tip struct sau class, se apeleaz constructorul
clasei.
Exemplu:
class Maina
{
public string marca;
public int pre;
}
class Test
{
static void Main(string[] args)
{
Maina m = new Masinaf); // Apelul constructorului
}
}
Observai c instanierea obiectului presupune de fapt apelul constructorului clasei:
Maina (). Toate clasele au un constructor. Putei defini proprii constructori. n
Capitolul 4.
67
{
public string marca;
public int pre;
public Maina(string m, int p) // Constructor
{
marca = m;
pre = p;
}
}
class Test
{
static void Main(string[] args)
{
// Maina m = new Maina (); // Greit! Nu mai exist
// constructorul implicit!
// Se invoc constructorul Maina(string, int)
Maina m = new Maina("Audi", 50000);
Console.Write(m.marca + " " + m.pret);
}
}
Ieire: Audi 50000
ATENIE !
n momentul n care ai definit cel puin un constructor, compilatorul nu mai
sintetizeaz constructorul implicit. De aceea, dac dorii i unul fr parametri,
trebuie s-l definii.
Exemplu:
class Maina
{
public string marca;
public int pre;
Partea I. Limbajul C#
68
public Maina()
// 1
{
marca = "Fiat";
pre = 1000;
}
public Maina(string m)
// 2
i
marca = m;
pre = 20000;
}
public Maina(int p)
// 3
{
marca = "Ford";
pre = p;
}
public M aina(string m, int p) // 4
{
marca = m;
pre = p;
>
}
Acum putei crea obiecte de tip Maina n mai multe moduri:
Maina
Maina
Maina
Maina
ml =new Maina();
// constructor 1
m2 =new Maina("Opel"); // constructor 2
m3 =new Maina(2000);
// constructor 3
m4 = new Maina("Renault", 15000);
// constructor 4
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 ales 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, atunci
este convenabil s definii un constructor de copiere (copy constructor). C# nu
furnizeaz un constructor de copiere implicit, aa cum ofer un constructor de
instan implicit. De aceea va trebui s-l definii dumneavoastr.
Exemplu:
Capitolul 4.
69
using System;
class C
{
private int x;
// Cmp privat
{
x = a;
}
public C(C ob)
{
x = ob.x;
// Constructor de copiere
}
public int GetX()
}
class TestCopyCtor
{
static void Main(string[] args)
{
C cl = new C(10);
// Apeleaza C(int)
C c2 = new C(cl); // Apeleaza C(C)
Console.WriteLine(c2.GetX()); // 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 n u me;
private int v a r s t a ;
Partea I. Limbajul C#
70
{
this.nume = nume;
this.varsta = varsta;
// cazul 1
// cazul 1
}
public Copil ModificVarsta(int varsta)
{
this.varsta = varsta;
return this;
// cazul 1
// cazul 2
}
public void AfiseazaO
{
Console.WriteLine(nume + " " + varsta);
}
}
class Test_this
{
static void Main(string[] args)
{
Copil c = new Copil("Alin",.17);
c .Afiseaza ();
// Ieire: Alin 17
c.ModificVarsta(18);
c.Afiseaza();
// Ieire: Alin 18
}
}
Ce s-ar fi ntmplat dac constructorul clasei s-ar fi definit astfel:
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 n
metodele clasei astfel: this .membru. n acest fel, this.nume = nume;
realizeaz o iniializare corect a cmpului nume.
Mai observm c metoda ModificVarsta () returneaz o referin la
obiectul curent. Cine este de fapt obiectul curent ? Asta nu vom ti, pn n
momentul n care metoda este apelat: c.ModificVarsta (18) ; Prin urmare, c
refer obiectul curent i this refer evident acelai obiect. De altfel, n momentul
apelului, this refer deja obiectul alocat cu new, pentru c c transfer n this
referina ctre obiect.
Exist i alte situaii n care avei nevoie de this, aa cum vom vedea mai
departe.
Capitolul 4.
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:
class Avion
// Membrii clasei
~Avion()
// Destructor
{
// Eliberarea resurselor gestionate de obiect
}
}
n majoritatea covritoare a cazurilor, nu vei avea de implementat un destructor,
deoareace C# are un garbage collector care distruge obiectele nefolositoare n
mod automat. Vei implementa un destructor doar n situaii n care obiectele
gestioneaz resurse care nu sunt controlate de .NET Framework.
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
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;
class Copil
{
p r i v a t e s t r i n g nume;
p r i v a t e int varsta;
// Cmpuri private
Partea I. Limbajul C#
72
// Constructor
{
nume - n ;
varsta = v;
}
public string Nume
// Proprietatea Nume
{
get
{
return nume;
}
set
{
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 = 2 0 ;
// set
Console.WriteLine(c.Nume + " " + c.Varsta); // get
F iecare proprietate returneaz i eventual seteaz i valoarea unui cmp privat. Sa u implementat dou proprieti: Nume i Varsta. Toate proprietile au tip.
Capitolul 4.
73
Prototipul proprietii este format din tipul returnat de ctre proprietate (aici
string, respectiv int) i numele proprietii (Nume i Varsta). Tipul proprietii,
s
s
Tipul proprietii
Numele proprietii
return nume;
set
{
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.
Partea I. Limbajul C#
74
Exemplu:
n set putei plasa orice cod defensiv de protecie a cmpului asociat
proprietii:
using System;
class ntreg
{
private int n;
public int N
{
get { return n; }
// Cmp privat
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 exist independent de existena instanelor clasei. Se
acceseaz prin numele clasei, la fel ca ali membri statici.
Capitolul 4.
75
Exemplu:
class Numr
{
private static int nr;
public static int Nr
// Cmp static
// Proprietate static
{
get { return nr; }
set { nr = value; }
}
}
class TestConst
{
static void Main(string[] args)
{
Numar.Nr = 100;
// set
System.Console.Write(Numar.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.
Exemplu:
using System;
class X
{
public int Valoare
{
get; set;
1
// Proprietate
// implementat
// n mod automat
Partea I. Limbajul C#
76
class TestAutoPropertie
{
static void Main(string[] args)
{
X x = new X ();
x.Valoare = 1 0 ;
Console.Write(x.Valoare);
// set
// 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 ref.
Nu pot fi suprancrcate.
Indexatori
Indexatorii permit instanelor unei clase sau ale unei structuri s fie indexate,
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:
TipReturnat this[int index]
{
get
{
/ / S e returneaz valoarea precizat prin index
}
set
{
// Se modific valoarea precizat prin index
}
}
TipReturnat este tipul de baz al indexrii. Parametrul index primete valoarea
Capitolul 4.
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 this[int index]
// Indexator
{
get
{
else
if (index > MAX)
return a[MAX];
else
return a [index];
>
set
{
}
}
1
;lass Testlndexer
fl
static void Main(string[] args)
{
Tablou t = new Tablou(100);
for (int i = 0; i < 10; i++)
t[i] = i;
// set
t [-1] = 10;
// set
Partea I. Limbajul C#
78
// get
Ieire:
10 1 2 3 4 5 6 7 8 9
Operatori de conversie
n capitolul 3, paragraful Conversii ntre tipuri, am vzut c ntre tipurile
predefinite se pot face conversii implicite sau explicite. Conversiile explicite se
realizeaz cu ajutorului operatorului ( ).
Exemplu:
double x = 2.3;
int y = 6;
x = y;
// Conversie implicit
y = (double)x; // Converise explicit
Sintax:
public static explicit operator Tipl
(Tip2 t)
{
// Cod care convertete n mod explicit t spre TipulClasei
}
sau
public static implicit operator Tipl[Tip2 t)
{
// Cod care convertete n mod implicit t spre TipulClasei
Capitolul 4.
79
Tipl este tipul spre care se face conversia. Tip2 este tipul care se convertete
spre Tipl. Unul dintre cele'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 int spre tipul Bancnota;
// conversii_explicite.cs
using System;
class 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;
}
}
class TestConversieExplicita
{
static void Main()
{
int val = 100;
Bancnota b = (Bancnota)val;
Console.WriteLine((int)b);
// Conversie explicit
// Conversie explcit
Partea I. Limbajul C#
80
Exemplul 2:
Modificm programul anterior, astfel nct s obinem operatori de conversii
implicite:
// conversii_iroplicite.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;
}
}
class TestConversielmplicita
l
static void Main()
// Conversie implicit
// Conversie implicit
}
}
Observai c nu a mai fost necesar utilizarea operatorului ( )
operator.
type cast
Clase interioare
O clas interioar (inner class sau nested class) este o clas a crei definiie
se gsete n interiorul definiiei altei clase.
1.
Capitolul 4.
81
Exemplu:
using System;
class A
// Clasa container
{
public class B // Clasa interioar
{
public void F() { Console.Write("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);
}
}
}
Partea I. Limbajul C#
82
{
Exterior ol = new Exterior(100);
// Instanierea unui obiect de tip Interior
Exterior.Interior o2 = new Exterior.Interior();
o 2 .Scrie(ol);
// Afieaz: 100
}
}
Continere
9
Cnd o clas are ca membri unul sau mai multe obiecte de tip clas, vorbim
despre coninere (containment) sau compoziie.
n figur, ilustrm clasa Calculator. Un
Calculator
calculator are mai multe componente. Acestea sunt
instane ale altor clase : Monitor, Tastatura,
Mouse i UnitateCentrala.
IMPORTANT
Tipul de relaie care se modeleaz n cazul continerii
este: HAS A (ARE UN, ARE O).
Exemplu:
Unitate central
Figura 4.1
{
private string marca;
// Maina ARE O caroserie c i ARE UN 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;
}
}
C onin ere
Capitolul 4.
83
class TestContinere
{
public static void Main()
{
Caroserie C = new Caroserie();
Motor M = new Motor();
Maina mea = new Maina(C, M, "Volvo");
}
}
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 G()
{
System.Console. WriteLine ("GO ") ;
}
}
public class TastPartialClass
{
static void Main()
{
A a = new A () ;
a.F<) ;
a . G() ;
}
}
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 Form l.Designer.es.
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:
se a le d c la s s A { / * . . . * / }
c la s s 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. n 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 F r a c ie , n felul acesta:
F r a c ie f l = new F r a c i e ( ) ;
F r a c ie f2 = new F r a c i e ( ) ;
F r a c ie f = f 1 + f 2;
n C# operatorii suprancrcai sunt metode statice ai crui parametri sunt
operanzii, iar valoarea returnat este rezultatul operaiei.
Sintaxa de declarare a unui operator pretinde folosirea cuvntului cheie
o p e ra to r, urmat de simbolul operatorului care se redefinete.
Capitolul 4.
85
Sintaxa
n cazul operatorilor binari:
public static Tip operator op(Tipl operandl, Tip2 operand2)
{
// operaii
}
n cazul operatorilor unari:
public static Tip operator op(Tip operand)
{
// 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 operatorii binari, cel puin unul dintre
cei doi operanzi trebuie s fie de tipul clasei. Tip este tipul de retur al operaiei i
de regul este un obiect de tipul clasei.
{
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 f2)
{
int A = fl.numrtor * f2.numitor +
f2.numrtor * fl.numitor;
Partea I. Limbajul C#
86
}
public static bool operator = (Fracie f1, Fracie f2)
{
if (fl.numitor == f2.numitor &&
fl.numrtor == f2.numrtor)
return true;
return false;
}
public static bool operator !=(Fracie f1, Fracie f2)
{
return !(fl == f2);
}
// Suprascrie Object.ToStringO
public override string ToStringO
{
String s = numrtor.ToString() + "/" +
numi tor. ToStringO ;
return s ;
}
public class TestFractie
{
static void M a i n ()
{
Fracie a = new Fracie(3, 4);
Console.WriteLine("a = {0}", a .ToString());
Fracie b = new Fracie(2, 4);
Console.WriteLine("b = {0}", b .ToString());
Fracie c = a + b; // operatort
Console.WriteLine("c = a + b = {0}",
c.ToStringO);
Fracie d = new Fracie(2, 4);
if (d == b)
// operator==
Console.WriteLine("d = b = {0}", d) ;
if (a != b)
// operator!=
Console.WriteLine(a + " != " + b);
a += b;
// operator +=
Capitolul 4.
87
}
}
Ieire:
a = 3/4
b = 1/2
c = a + b = 5/4
d = b = 1/2
3/4 != 1/2
a = 5/4
De retinut:
>
>
>
>
>
Metoda ToString()
n clasa Fracie, am definit metoda ToString(). 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 returna 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 override. 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 ToString ().
Partea I. Limbajul C#
88
private int n;
public ntreg(int i)
{
n = i;
// Constructor
}
// 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}", n);
return s;
}
}
public class TestOpUnari
{
static void Main()
{
ntreg x = new ntreg(10);
x++;
// Incrementare
Console.WriteLine(x + " " + -x) ; / /
Scrie: 11 -11
}
}
NOT:
Nu este nevoie s creai dou versiuni diferite ale. operatorului ++ ca s
suporte incrementare prefixat i sufixat. O singur versiune este suficient, iar
compilatorul are grij s implementeze diferenierea ntre prefixare i sufixare.
IMPORTANT___________________________________________
Este recomandabil s nu modificai operanzii pasai metodelor operator. In
loc de aceasta, creai noi instane de tipul valorii de retur i returnai aceste
instane. Urmnd aceast practic, vei evita probleme la depanare.
Capitolul 4.
89
Operatori relaionali: = cu !=, < cu >, <= cu >= (acetia trebuie suprancrcai n
perechi).
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:
Structurile sunt tipuri valoare, iar clasele sunt tipuri referin.
Nu suport motenirea.
Nu suport constructori fr parametri.
Nu au destructori.
Sintaxa:
[ModificatorAcces] struct
{
II
NumeStructur
membrii structurii
Exemplu:
using System;
struct Punct
i
private double x;
private double y;
public Punct(double _x, double _y) // Constructor
{
x = _x;
y = _y;
}
public double X
{
get { return x; }
// Proprietatea X
Partea I. Limbajul C#
90
set { x = value; }
>
public double Y
// Proprietatea Y
{
get { return y; }
set { y = value; }
}
}
class TestStruct
{
static void M a i n (string[] args)
{
Punct pi = new Punct(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 instaniate 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.
Interfete
9
Sintaxa minimal:
[modificatori] interface Numelnterfat
{
// Corpul interfeei
}
Modificatorii pot fi public, private, protected, internal, protected
internal. Cuvntul cheie interface preced numele interfeei. Este o practic
comun ca numele interfeei s nceap cu litera I. Exemple: icomparable,
ICloneable, IControl, etc.
Capitolul 4.
91
interface II { /*...*/ }
interface 12 { /*...*/ }
class C : II, 12
{ /*...*/ }
Exemplu:
using System;
interface IPrintable
{
void Print(string s);
}
public class Mail : IPrintable
{
private string s;
public Mail(string s)
// Constructor
{
this.s = s;
}
// Implementarea metodei interfeei (obligatoriu!)
public void Print(string a)
{
Console.WriteLine(s + a);
1
)
public class TestOpUnari
{
static void Main()
{
Mail m = new M ail("Prietenilor mei ");
m .Print("Salut!");
}
}
Ieire:
Prietenilor mei Salut!
92
Partea I. Limbajul C#
Motenire
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 subobiect, un obiect de tipul
Figura 4.2
Specializare i generalizare
Una dintre cele mai importante relaii ntre obiecte n lumea real este
specializarea, care poate fi descris ca o relaie IS 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 este 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.
Capitolul 4.
93
Implementarea motenirii
Fie clasa A care motenete clasa B.
motenire:
class B
// B - C l a s a d e b a z
{
/ / M e m b rii c l a s e i B
}
class A : B
/ / A - C la s a d e r i v a t
i
/ / M e m b rii c l a s e i A
>
Sintaxa A : B se numete specificaie de clas de baz (base class specification).
Membrii clasei derivate sunt:
> Membrii definii n propria clas.
> Membrii clasei de baz.
Se spune despre o clas c extinde 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.
Clasa A
Metoda 2
Clasa B
Metoda 1
Cmpul 1
Cmpul 2
Clasa B
Metoda 1
Cmpul 1
Partea I. Limbajul C#
94
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. n 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
// din object
class Avion
{
// membrii clasei
// Derivare explicit
// din object
class Avion : object
{
// membrii clasei
c la s s A : B, I I ,
{
}
>
// Incorect
12, 13
c la s s A : I I ,
{
}
B, 12, 13
}
>
Capitolul 4.
95
// Corect
class C : D { }
class B : C { }
class A : B { }
// Cmpuri
// Proprietate
{
set { hrana = value; }
get { return hrana; }
}
protected void SeHraneste()
// Metod
1
Console.WriteLine("Animalul se hrnete");
>
1
class Pisica : Animal
{
private string rasa;
public string Rasa
{
set { rasa = value;
get { return rasa;
}
}
}
public void Toarce()
{
/* Membrii protejai i cei publici ai clasei de baz
pot fi accesai din metodele clasei derivate */
/ / hrana = "lapte";
}
}
Partea I. Limbajul C#
96
{
//
//
//
II
//
II
II
Ieire:
Animalul se hrnete
Pisica toarce
Capitolul 4.
97
{
public Baza()
{
Console.WriteLine("Constructor Baza");
}
}
class Derivat ; Baza
{
public Derivat()
{
Console.WriteLine("Constructor Derivat);
}
}
public class TestConstructor
{
static void. Main()
{
}
Derivat d;
d = new Derivat(); // Apelul constructorului clasei
// derivate
)
Ieire:
Constructor Baza
Constructor Derivat
{
}
Partea I. Limbajul C#
98
Dac constructorul bazei are parametri, atunci apelul implicit nu poate avea loc.
Constructorul derivat trebuie s invoce n mod explicit constructorul bazei,
furnizndu-i i argumentele corespunztoare:
Exemplu:
using System;
class Baza
{
private int x;
public Baza(int y)
{
x = y;
>
}
class Derivat : Baza
{
private char c;
public Derivat(char a, int b)
: b ase(b)
{
c = a;
}
}
public class TestConstructor
{
static void Main()
{
Derivat d = new Derivat('T', 10);
}
}
Constructorul clasei derivate trebuie s aib suficieni parametri pentru a iniializa
i cmpurile bazei.
Cum se construiete o instan a clasei derivate ?
Cnd se invoc constructorul clasei derivate, ordinea construciei instanei este:
1. Iniializarea membrilor de tip instan a clasei derivate.
2. Apelul constructorului clasei de baz.
3. Executarea corpului constructorui clasei derivate.
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.
Capitolul 4.
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 Metoda()
{
Console.WriteLine("Baza.Metoda() " ) ;
}
}
class Derivat : Baza
{
new public int camp = 20;
new public void Metoda()
{
b as e.Metoda();
Console.WriteLine("Derivat.Metoda() " + base.camp);
}
}
public class TestMembriAscunsi
{
static void Main()
{
Derivat d = new Derivat();
d.Metoda();
}
}
Ieire:
Baza.Metoda()
Derivat.Metoda() 10
Baza.Metoda()
Partea I. Limbajul C#
100
Polimorfism
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
i
Dac avei o referin la un obiect al clasei derivate, putei obine o referin
la partea de baz a obiectului, folosind operatorul de conversie () ca mai jos:
class Baza
{
public void Metoda()
{
System.Console.WriteLine("Baza.Metoda()") ;
}
}
class Derivat : Baza
{
public void Metoda() // sau new public void Metoda()
{
System.Console.WriteLine("Derivat.Metoda()");
}
}
public class TestConversieRef
{
static void Main()
{
Derivat d = new Derivat();
d.Metoda();
// Upcast
Baza b = (Baza)d;
b.Metoda () ;
}
}
Ieire:
Derivat.Metoda()
Baza.Metoda()
Capitolul 4.
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
a 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 Metoda()
{
Console.WriteLine("Metoda() din Baza");
}
1
class Derivat : Baza
{
override public void Metoda()
{
Console.WriteLine("Metoda() din Derivat");
}
}
class TestPolimorfism
{
static void Main(string[} args)
Partea I. Limbajul C#
102
{
Derivat d = new Derivat();
d.Metoda();
// Ieire: "Metoda() din Derivat"
// Polimorfism
Baza b = new Baza();
b.MetodaQ;
// Ieire: "Metoda() din Baza"
b = new Derivat();
b.Metoda();
// Ieire: "MetodaO din Derivat"
>
}
}
Primul apel b.Metoda ( ) ; 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("F() din A"); }
}
class B : A { }
class C : B
// B nu redefinete F()
{
override public void F()
{ Console.WriteLine(" F () din C"); }
}
class D : C { }
// D nu redefinete F()
class Test
{
static void Main(string[] args)
{
A a = new B ();
a F () ;
a = new C() ;
a .F () ;
a = new D() ;
a .F () ;
}
}
//
//
//
//
//
//
Capitolul 4.
103
Dac o referin de tipul clasei de baz refer un obiect de tip derivat i prin acea
-eferin 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
j
Modificatorul
s e a le d
Exemplu:
class A
{
protected virtual void F() { /*...*/ }
protected virtual void G{) { /*...*/ }
}
class B
{
: A
}
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.
Partea I. Limbajul C#
104
Utilitatea polimorfismului
n practic se opereaz deseori cu colecii de obiecte. Mai precis, cu colecii
de referine la obiecte. Dac obiectele sunt legate printr-o relaie de motenire
avnd o clas de baz comun, atunci nu trebuie ca ele s fie de acelai tip. Dac
toate obiectele redefinesc o metod virtual a clasei de baz, atunci putei invoca
aceast metod pentru fiecare obiect.
using System;
class LimbaVorbita
// Clasa de baz
{
virtual public void SeVorbeste()
{ } // nu va fi invocat
}
class Engleza : LimbaVorbita
{
override public void SeVorbesteO
{ Console.WriteLine("Engleza") ; }
}
class Franceza : LimbaVorbita
{
override public void SeVorbesteO
{ Console.WriteLine ("Franceza"); }
}
class Spaniola : LimbaVorbita
{
override public void SeVorbesteO
{ Console.WriteLine("Spaniola") ; }
}
class Catalana : Spaniola
{
override public void SeVorbesteO
{ Console.WriteLine("Catalana") ; }
}
class Test
{
static void Main(string[] args)
{
LimbaVorbita[] L = new LimbaVorbita[4];
L [0] = new Engleza(); L[l] = new Franceza();
L [2] = new Spaniola(); L[3] = new Catalana();
foreach (LimbaVorbita lv in L)
lv.SeVorbeste();
}
}
Ieire:
Engleza
Franceza
Spaniola
Catalana
Capitolul 4.
105
Tabloul LimbaVorbita reine referine ale unor obiecte de tipuri diferite, dar care
sunt legate prin relaie de motenire, avnd ca baz a ierarhiei clasa
LimbaVorbita. Dac relaia de motenire nu ar exista, atunci referinele ar fi
trebuit s fie de acelai tip. Programul implementeaz polimorfismul. Interfaa de
apelare unic ( lv. SeVorbeste () ) care se utilizeaz pentru fiecare obiect, duce
la aciuni specifice, n funcie de obiectul referit.
Rezumatul capitolului
Clasele sunt entiti logice care modeleaz obiecte din lumea real sau
obiecte abstracte. Clasele ncapsuleaz date i metode care opereaz cu
aceste date.
Constructorii unei clase sunt metode speciale care au rolul de a creea, a
construi obiecte.
Destructorul clasei este o metod special care distruge instanele
claselor.
Proprietile sunt membri ai clasei cu ajutorul crora se acceseaz
cmpurile private ca i cnd ar fi fost declarate public, fr ca prin aceasta
s se ncalce principiul proteciei datelor.
Suprancrcarea operatorilor este mecanismul prin care instanele clasei
pot fi integrate n expresii aritmetice sau logice n calitate de operanzi, cu
utilizarea operatorilor specifici tipurilor predefinite:
<, >, etc.
Motenirea este mecanismul care permite s s se defineasc o nou
clas care incorporeaz i extinde o clas existent.
Polimorfismul este caracteristica unei variabile referin de a putea referi
obiecte de tipuri diferite. C# admite polimorfism bazat pe relaia de
motenire.
ntrebri i exerciii
1.
Partea I. Limbajul C#
106
Capitolul 5
Delegri
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 delegare 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
tipurilor (type-safe). Capacitatea unei delegri de a invoca mai multe metode se
numete multicasting.
Declarare
O delegare este un tip, aa cum i clasele sunt tipuri. Un tip delegare
trebuie declarat nainte de crearea obiectelor de tipul su. Declararea este creat
cu cuvntul cheie delegate, urmat de tipul de retur i de signatura metodelor pe
care delegarea le accept.
Exemplu:
delegate void DelegareaMea(int x ) ;
Capitolul 5.
107
d = new DelegareaMea{ReferinOblect.Metod);
sau
d = new DelegareaMea(NumeClas .MetodStatic) ;
2.
d = ReferinObiect.Metod;
sau
d = NumeClas.MetodStatic;
{
// Metod de instan care potrivete delegrii
public void F (string s)
{
Console.WriteLine(s + "F() ") ;
1
// 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
1
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()
Partea I. Limbajul C#
108
}
}
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 -=.
{
x += 2;
return x;
}
public int G()
{
x += 6;
return x;
}
}
class Program
{
Capitolul 5.
109
{
Test s = new TestQ ;
DelTest d;
// Referin la tipul delegat
// Atam metode delegrii d
d = s.F;
// Lista de invocare: F()
d += s.G;
// Lista de invocare: F(), G()
d += s.F;
// Lista de invocare: F(), G(), F()
Console.WriteLine(d()); // Afieaz: 10
}
}
Evenimente
Aplicaiile cu interfa grafic cu utilizatorul sunt sensibile la evenimente ca:
click cu mouse-ul pe suprafaa unei ferestre, apsarea unei taste, deplasarea
mouse-ului deasupra unui control, etc. Sistemul de operare ntiineaz fereastra
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 ioc evenimentul
se numesc subscribers. Clasele care subscriu evenimentului (clasele subscriber)
definesc metode pentru tratarea acestui eveniment (event handler-e).
Exist 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.
Evenimentul i handler-e le de evenimente trebuie s aib o semntur i
un tip de retur identice.
no
Partea I. Limbajul C#
2.
{
while
(true)
{
// Execuia programului se ntrerupe 3 secunde
System.Threading.Thread.Sleep(3000);
/ / N e asigurm c exist metode nregistrate
if (eveniment != nuli)
eveniment(); // Declaneaz evenimentul
Capitolul 5.
111
}
/ Clase Subscr i b e r
class A
{
public void HandlerAQ
{
Console.WriteLine("Obiect A, notificat la {0}",
DateTime.Now.) ;
}
}
class B
{
public void HandlerBQ
{
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.eveniment += a.HandlerA; // nregistrarea metodelor
p.eveniment += b.HandlerB; // handler
// Apeleaz metoda care declaneaz evenimentul
p.Declaneaz ();
1
1
Programul afieaz la fiecare trei secunde, cte dou linii:
Obiect
Obiect
Obiect
Obiect
A,
B,
A,
B,
notificat
notificat
notificat
notificat
la
la
la
la
12.06.2008
12.06.2008
12.06.2008
12.06.2008
10:13:22
10:13:22
10:13:25
10:13:25
112
Partea I. Limbajul C#
IMPORTANT___________________________________________
nregistrarea metodelor ataate unui eveniment se face cu operatorul +=,
iar ndeprtarea lor din lista de invocare, se face cu -=.
i
public void HandlerB(object sender, EventArgs e)
Capitolul 5.
113
1
private DateTime momentul;
public DateTime Momentul
// Cmp
// Proprietate
1
set
{
momentul = value;
}
get
{
return this.momentul;
}
}
)
// Declar tipul delegat cu prototipul cerut de .Net
public delegate void Timp(object sender, MyEventArgs ev);
public class Publisher
{
public event Timp eveniment;
// Declar evenimentul
{
while
(true)
{
// Execuia programului se ntrerupe 3 secunde
System.Threading.Thread.Sleep(3000);
// Ne asigurm ca exist
if (eveniment != null)
{
// metode nregistrate
MyEventArgs ev = new MyEventArgs();
e v .Momentul = DateTime.Now;
// Declaneaz invocarea handler-elor
eveniment(this, ev);
}
}
}
}
// Clase Subscriber
Partea I. Limbajul C#
114
class A
{
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.Declaneaz();
}
}
Ieirea programului este identic cu cea a programului anterior.
De retinut:
j
Dac vrei s scriei cod eficient, vei trata evenimentele folosind clasele de
baz EventHandler i EventArgs, iar delegrile vor avea prototipul compatibil
.NET, chiar dac C# admite orice model delegat.
Generice
Programarea Generic 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
Capitolul 5.
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 re
public Stiva(int max)
{ a = new i n t [max]; }
public void Push(int val)
{ a[n++] = val; }
public int Pop()
{ return a [ n ]; }
1
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 tipuri parametrizate. 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)
{ a = new T [max]; }
public void Push(T val)
{ a[n++] = val; }
public T Pop()
{ return a[--n]; }
// Constructor
Partea I. Limbajul C#
116
{
static void Main()
{
// Se creeaz o stiv de int
(T = int)
Stiva<int> sl = new Stiva<int>(100);
s l .Push(2);
s l .Push(4);
s l .Push(6);
Console .WriteLine (sl.Pop () + " " + sl.PopO +
sl.PopO ) ;
// Se creeaz o stiv de string (T = string)
Stiva<string> s2 = new Stiva<string>(50);
s 2 .Push("Marcel");
s 2 .Push("Ionel");
s 2 .Push("Alin");
Console.WriteLine(s2.Pop() + " " + s2.Pop() +
s2.Pop ()) ;
II
II
If
II
1
}
Ieire:
6 4 2
Alin Ionel Marcel
{
private TI a;
private T2 b;
public A(TI a, T2 b)
{
this.a = a;
this.b = b;
// Constructor
Capitolul 5.
117
{
Console.WriteLine ( a + " " + b) ;
}
public class TestGeneric
1
static void Main()
1
A<string, int> ml = new A<string, int>("Alin", 18);
m l .Print();
A<string, string> m2 = new A<string, string>("UNU",
"DOI");
m2 .Print () ;
A<double, char> m3 = new A<double, char>(2.3, 'F');
m3.Print();
)
}
ieire:
Alin 18
1 2
2.3 F
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
Partea I. Limbajul C#
118
this.u = u;
}
// Metoda generic - are proprii parametri generici
public void F<V1, V2>(V1 a, V2 b)
{
Console.WriteLine(a.ToString() + " " + u .ToString() +
" " + 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<char>('F ');
c2.F<string, int>("Iulia", 8);
// U = char
}
}
Ieire:
S traiti 104 ani!
Iulia F 8
Capitolul 5.
119
Colecii
!
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,
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.
i
public static void Main()
{
// Declar o stiv vid cu elemente de tip string
Stack<string> st = new Stack<string>();
// Adaug cteva elemente n stiv
st.Push("UNU"); st.Push("DOI");
s t .Push("TREI"); s t .Push("PATRU");
Console.WriteLine("Nr. de elemente:
{0}", st.Count);
}
}
Ieire:
N r . de elemente: 4
PATRU
TREI
Partea I. Limbajul C#
120
DOI
UNU
Scoate 'PATRU'
Vrful stivei: 3
{
public static void Main()
t
// Creeaz lista copii cu elemente de tip string
List<string> copii = new List<string>();
// Adaug elemente n list
copii.A d d ("Ionel"); copii.Add("Radu");
copii.Add("Viorel"); copii.Add("Adisor");
copii.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 \"Alin\" " +
"pe poziia 2:");
copii.Insert(2, "Alin");
foreach (string c in copii)
Console.Write(c + " ");
Console.WriteLine("\ncopii[3] = {0}", copii[3]);
Console.WriteLine("\nSorteaza alfabetic: ");
copii.Sort();
for (int i = 0; i < copii.Count; i++ )
Console.Write(copii[i] + " ");
Capitolul 5.
121
Console.WriteLine("\n\nSterge \"Nelutu\":");
copii.Remove("Nelutu");
freach (string c in copii)
Console.Write(c + " ");
Console.WriteLine("\n\nSterge lista de copii:");
copii.Clear ();
Console.WriteLine("Nr. copii: {0}", copii.Count);
ieire:
Ionel Radu Viorel Adisor Nelutu
N r . copii: 5
Viorel exista ? true
Insereaz "Alin" pe poziia 2:
Ionel Radul Alin Viorel Adisor Nelutu
copii[3] = Viorel
Sorteazs alfabetic:
Adisor Alin Ionel Nelutu Radu Viorel
terge "Nelutu":
Adisor Alin Ionel Radu Viorel
terge lista de copii:
N r . de copi: 0
Exemplu:
using System;
using System.Collections.Generic;
Partea I. Limbajul C#
122
{
public static void Main()
{
// Un dicionar cu cheia string i valoarea int
Dictionary<string, int> T =
new Dictionary<string, int>();
// Adaug elemente in dicionar.
T.A d d ("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:
T ["Vlad"]) ;
{0}",
}
}
Ieire:
Cheia Vlad are valoarea: 213048
Cheia Vlad are valoarea: 215773
Capitolul 5.
Ionescu
Pop
Vlad
Cazacu
Dragnea
Simion
123
209791
232145
215773
219465
279950
200371
Tratarea excepiilor
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 handler 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
}
catch(System.Execption e)
{
// Cod care trateaz excepia
1
finally
{
II Cod care se execut dup try-catch indiferent
}
Exemplu:
using System;
class TestExceptii
Partea I. Limbajul 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 .ToString());
}
finally
{
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
8
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
elibereze resursele (fiiere deschise, memorie alocat, etc.). Dac excepia se
produce, atunci blocul finally se execut dup catch.
Blocul finally poate s lipseasc. Pentru acelai bloc try, se pot declara mai
multe blocuri catch, fiecare dintre ele, preciznd o posibil excepie care se poate
lansa din try.
Manevrarea stringurilor
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.
Capitolul 5.
125
Operaii i metode
string definete operatorii relaionali =, != i operatorii de concatenare +,
+=. Definete de asemenea mai multe 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,
/ / u n 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.
Exemplu:
using System;
class Teststring
{
public static void Main()
{
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
Partea I. Limbajul C#
Exemplu:
f l o a t x = 1 23 .34 5 6F ; d o u b le y = 2 3 .4 5 8 9 ; s t r i n g s;
s = S t r i n g . F o rm a t( "x = { 0 ,1 2 :E 3 } \n y = { 1 , 1 2 : F 2 } " , x , y ) ;
C o n s o le . W r ite L in e ( s ) ;
A f i e a z :
x =
1 . 233E+002
y =
2 3 .4 6
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 ,1 2 :F 2 } 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 ,- 1 2 ;F 2 }.
Stringurile se pot formata pentru afiare dup aceleai reguli i cu ajutorul
metodelor C o n so le .W r ite () i C o n sole .W r ite L in e ():
Exemplu:
d o u b le x = 2 3 . 4 5 8 9 ;
C o n s o le .W r ite L in e ( " |x = { 0 , 1 0 : F 2 } | " , x ) ;
C o n s o le .W r ite L in e ( " |x = { 0 , - 1 0 : F2 } | " , x ) ;
Afieaz:
|x =
23.46|
|x = 23.46
|
Exemplu :
in t n = i n t . Parse("652");
/ / n = 652
d o u b le d = d o u b l e . P a r s e ( " - 2 0 . 2 3 5 " ) ; / / d = - 2 0 . 2 3 5
Capitolul 5.
127
{
char[] sep = { '\n', ' 1, '.', '!' } ;
string s = "12
27\n... 496!";
string[] w = nuli;
// Tabloul w preia substringurile fr separatori din s
w = s .Split(sep,StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < w.Length; i++)
{
int x = int.Parse(w[i]) ;
Partea I. Limbajul C#
128
Console.Write(w[i] +
}
}
}
Ieire:
12_ 27_ 496_
{
string fin = @"C:\teste\numere.in";
string fout = @"C:\teste\numere.out";
// Deschide fiierele de intrare i de ieire
StreamReader sr = new StreamReader(fin);
StreamWriter sw = new StreamWriter(fout);
string[] s = nuli;
string linie = nuli;
Capitolul 5.
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
sw.Wr ite("{0, -5}", x) ; // O scrie n fiier
}
sw.WriteLine();
}
sr.Close();
sw.Close();
// nchide fiierele
}
}
335
25
1
561
5
773
76
67
Observaii:
i
>
>
>
>
Partea I. Limbajul C#
130
Rezumatul capitolului
generici.
tables).
Tipurile predefinite (int, double, float, etc.) definesc metoda Parse ().
Aceasta preia stringul citit i l transform n valoarea numeric
corespunztoare.
Clasele
StreamReader i StreamWriter citesc, respectiv scriu
caractere din stream-uh. Conin metodele ReadLine(), respectiv
writeLine (). Acestea citesc sau scriu din stream pn la caracterul
newline.
ntrebri i exerciii
1.
2.
3.
Capitolul 6.
131
Partea a II - a
Programare Windows
cu Visual C# 2008 Express Edition
Capitolul 6
Aplicaii
Aplicaii
Aplicaii
Aplicaii
Aplicaiile de tip Windows Forms i cele WFP faciliteaz prin designer-ele integrate
dezvoltarea interfeelor grafice cu utilizatorul (user interface).
1.
4.
File
jJ
Edit
j
View
J
Project
Ctt2 0 0 8
Build
.....
iS
Toolbox
xj;-- -
-r 9 X
Express E ditio n
Debug
Data
Format
Pointer
Forml.cs [Design]*
8 Foriril
fib) Button
0
Checkbox
i|>; CheckedListBox
T f ComboBox
2 ? DateTimePicker
Tools
Window
Help
* ft....
|
.A. .....
......
.<2L :i . i!
......
buttonl
..
f[ .2'7 1
.. -
r ? X
Label
A LinkLabel
l&i*j ListBox
UstView
5.
6.
Capitolul 6.
Toolbox
133
b u ttonl System.Windows.Forms.
- Common Controls
|^
i n i k
Pointer
|abj Button
: 0
CheckBox
CheckedListBox
Imagelndex
ImageKey
ImageList
I
I (none)
(none)
RightToLeft
No
ComboBox
A
A
1 (none)
Apasa
DateTimePicker
Text Align
Labei
TextlmageRelc Overlay
LinkLabel
UseMnemonic
MiddleCenter
True
UseVisualStylel True
; i f ryj ListBox
UseWaitCursor False
; V ' ListView
B !iefu:v.
7.
8.
{
MessageBox.Show("Salut lume !");
}
9.
' -.rorml
V using
using
usmg
using
using
using
: using
: using
, button1_Ck>Xob|ed
System;
System.Collections.Generic;
System.CoroponentKode1 ;
System.Data;
System.Drawing;
System.Linq;
System.Text;
System.Windows.Forms;
Fereastra
aplicaiei
; namespace Salut
;f
public partial class Foiini : Form
{
public FormlO
{
InitialiseComponent();
>
Message Box
Observaie:
j
" 1 ---I
Fig. 6.1
S t r u c t u r a ie r a r h ic a c o n t r o a l e l o r . 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 Properties 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
iniiele pot fi stabilite design-time n aceast fereastr. Desigur c aceste
proprieti se pot modifica programatic n timpul execuiei programului.
Capitolul 6.
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 conduse de evenimente
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
buttonl_ciick () 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 evenimentelor
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.
{
// Cod care trateaz evenimentul
}
sender 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 C lic k E v e n t
Pentru realizarea proiectului, urmai paii de mai jos:
1.
2.
3.
4.
5.
6.
7.
8.
9.
A doua variant este s dai alt nume metodei, din fereastra Properties,
editnd cmpul din dreapta etichetei Click. Putei pune de pild numele
eveniment_Click, apoi apsai Enter.
Capitolul 6.
137
buton System.Windows.Forms.Button
Common Controls
I ^ Pointer
Button
ChecKBox
eveniment_Click y
Apasare
MouseCaptureChangec
CheckedListBox
MouseClick
If* ComboBox
validare
DateTimePicker
Paint
B Behavior
Label
LinkLabel
ChangeUICues
ControlAdded
ControlRemoved
1*1 ListBox
ListView
i-
MaskedTextBox
HelpRequested
QueryAccessibilityHelp
MonthCalendar
StyleChanged
Notifylcon
SystemColorsChanged
{
Control c = (Control)sender;
// Conversie explicit
//
(downcast)
MessageBox.Show("Ati fcut click pe controlul: " +
c.Name + " cu eticheta: " + c.Text);
}1
11. Acum subscriem cu acelai handler, pentru evenimentele generate de
CheckBox i TextBox. Selectai pe rnd cte unul dintre controale, i din
fereastra Properties, apsai butonul Events, apoi alegei din lista din
dreapta etichetei Click acelai handler. eveniment_ciicJc.
ve rif System,Windows .Forms. CheckBox
,0
Apasare
MouseCaptureChar eveniment_Click
MouseClick
O
-----------------------
validare
0 Behavror
1
ChangeUICues
ControlAdded
yA S M
Apasare
F I validare
OK
Observaii:
j
Fiierul P ro g ra m .e s
Fiierul conine metoda Main(). Este punctul de intrare n aplicaie. n
Solution Explorer, facei click drept pe Program.es i alegei View Code:
Capitolul 6.
139
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormaMea());
}
Partea important este faptul c metoda Main() din clasa P r o g r a m apeleaz
metoda Run ( ) .R u n () e metod static a clasei Application. R u n () 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 F o rm a M e a .e s
Fiierul implementeaz n general constructorii clasei, i toate metodele
definite de programator.
n Solution Explorer, facei click drept pe fiierul F o r m a M e a .cs i alegei
View Code:
II fragment din codul FormaMea.es
namespace C lickEvent
{
p u bl ic p a rtial class FormaMea
: Form
{
p u b l i c F o r m a M e a ()
{
I n i t i a l i z e C o m p o n e n t ();
}
}
p r i va te v o i d e v e n i m e n t _ C l i c k (object sender, E v e n tArgs e)
{
Control c = (Control)sender;
// Conversie explicit
// (downcast)
MessageBox.Show("Ati fcut click pe controlul: " +
c.Name + " cu eticheta: " + c.Text);
}
}
Observaii:
public FormaMea)
// Constructor
{
// Aici putei apela metode.
// Controalele nu exist nc
InitializeComponent();
// Si aici putei apela metode.
// Forma i controalele sunt deja create
{
partial class FormaMea
{
II...
private void InitializeComponent()
{
II...
}
private System.Windows.Forms.Button buton;
private System.Windows.Forms.CheckBox verif;
private System.Windows.Forms.TextBox edit;
}
}
Capitolul 6.
141
(
// Instanierea (crearea) celor trei controale
// prin apelul constructorilor
t h i s . b u to n = new S y s te m .W in d o w s . F o rm s . B u t t o n ( ) ;
t h i s . v e r i f = new S y s te m .W in d o w s . F o rm s . C h e c k B o x ( ) ;
th is .e d it
= new S y s te m .W in d o w s . F o rm s . T e x t B o x ( ) ;
23);
II...
II Adugarea controalelor pe form
t h i s . C o n tr o ls .A d d (t h is . e d i t ) ;
th is .C o n tr o ls .A d d (th is . v e r i f ) ;
t h i s . C o n tr o ls .A d d (th is .b u to n );
Aplicaia R a is e E v e n t
1. n meniul File, alegei NewProject.
2.
3.
Capitolul 6.
143
4.
5.
{
// Declaneaz evenimentul Click pentru al doilea
// buton
button2.PerformClick() ;
1
6.
{
MessageBox.Show("Ati fcut click butonul doi !");
}
7.
b u (to n 2
Aplicaia D tp R u n tim e
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 File, alegei NewProject.
2. n panoul Templates, selectai Windows Forms Application.
3. In cmpul Name, scriei de exemplu DtpRuntime ca nume de proiect.
4. Din Toolbox, tragei pe form un buton.
5. Facei dublu click pe suprafaa butonului pentru a trata evenimentul Click,
n Editorul de Cod, 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
this.Controls.A d d (dtp);
L Ma Mi J V
1
7
14
21
28
j
2
88
15 16
22 23
29 30
S 0
3 4 5 6
10
11 12 13
17 18 19 20
2425
27
31
iAzi: 26.07.2008
Capitolul 7.
145
Capitolul 7
_a 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 System.Windows.Forms se definesc trei controale care
deriv din clasa ButtonBase: Button, CheckBox i RadioButton.
Button 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
Properties. 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 Contents. n panoul din stnga, expandai nodul .Net Framework
SDK. Apoi expandai .Net Framework Class Library. Expandnd mai departe
nodul System.Windows.Forms Namespace, ntreaga galerie de clase de tip
control v este accesibil cu toate informaiile necesare.
Revenind la Button, acesta poate genera mai multe tipuri de evenimente,
ns n proporie covritoare, evenimentul Click este cel mai folosit.
Aplicaia B u tto n E x a m p le
Vom face o mic aplicaie care trateaz alte dou tipuri de evenimente i
pune n eviden cteva dintre proprietile butoanelor.
1.
4.
5. n panoul din stnga aducei un buton, iar n cel din dreapta, plasai dou
butoane.
6.
{
/ / l readucem la forma i eticheta iniiale
buttonl.Dock = DockStyle.None;
buttonl.Text = "buttonl";
}
else
// l andocm i schimbm eticheta
buttonl.Dock = DockStyle.Fill;
buttonl.Text = "Fill !!";
}
7.
8.
Capitolul 7.
147
}
9.
}
10. Selectai button3 i din fereastra Properties setai proprietatea Text la
valoarea ieire.
11. Facei dublu click pe butonul cu eticheta Ieire, pentru a trata evenimentul
Click. 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 * .
Aplicaia L a b e lE xa m p le
Vom realiza un proiect care exemplific cel mai simplu mod de utilizare a
etichetelor.
1. n meniul File, alegei NewProject.
2. n panoul Templates, selectai Windows Forms Application.
3.
4.
5.
6.
AutoEllipsis
ContextMenuStrip
Enabled
B
(none)
True
9; 2 4
Start
Length
24
LinkBehavior
7.
False
SystemDefault
Capitolul 7.
149
}
8.
U n control Labei
9.
{
linkLabel2.LinkVisited = true;
labell.Text = "S-a lansat Notepad";
// Folosete metoda Start() pentru a lansa Notepad
System.Diagnostics.Process.Start("notepad");
aiiura
S-a lansat Notepad
Vizitai www.vahoo.com
Lansai Notepad
Observaii:
>
{
// Creaz o etichet
LinkLabel Ink = new LinkLabel();
Ink.Text = "Vizitai www.yahoo.com";
// 9 -poziia primului caracter al link-ului
Ink.LinkArea = new LinkArea(9, 24);
// Poziia de amplasare pe form
Ink.Location = new Point(20, 20);
// Adaug controlul pe forma curent
this.Controls.Add(Ink);
>
Capitolul 7.
151
Aplicaia G ro u p R ad io C h e c k
Proiectul ilustreaz un mod simplu de utilizare a controalelor RadioButton,
CheckBox i GroupBox.
1.
4.
5.
GroupBox.
6.
152
7.
8.
9.
1II3I
Excursii
Tara
Transport
Austria
I ! Avionul
Grecia
[~~l Balonul
Frana
Italia
Germania
Verifica
Ieire
10. Facei dublu click pe butonul Verifica, pentru a trata evenimentul Click. n
handler-ul de eveniment, scriei codul evideniat cu bold:
private void buttonl_Click(object sender,
EventArgs e)
Capitolul 7.
153
{
string msg = "Vom pleca in ";
// Verific care dintre butoanele radio e apsat
if (radioButtonl.Checked)
msg += radioButtonl.Text;
if (radioButton2.Checked)
msg += radioButton2.Text;
if (radioButton3.Checked)
msg += radioButton3.Text;
if (radioButton4.Checked)
msg += radioButton4.Text;
if (radioButton5.Checked)
msg += radioButton5.Text;
// 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.Text;
// Afieaz mesajul
MessageBox.Show(msg + " !");
// Restablete starea iniial
checkBoxl.Checked = false;
checkBox2.Checked = false;
radioButtonl.Checked = true;
1
11. Facei dublu click pe butonul Ieire, pentru tratarea evenimentului Click. n
Editorul de Cod vei scrie:
private void button2_Click(object sender, EventArgs e)
{
Application.Exit(); // Ieire din aplicaie
}
12. Rulai aplicaia cu F5 sau acionai butonul
La rulare, obinei:
154
Excursii
T ara
T ransport
Austria
Avionul
Grecia
Balonul
Frana
Italia
Germania
Verifica
Ieire
Controlul TextBox
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.
PassworChar
Text
Metode:
C o p y ()
Paste()
Capitolul 7.
Cut ()
Clear ()
Select()
SetBounds()
Undo()
155
Evenimente:
-
Click
GotFocus
Leave
TextChanged
Se declaneaz
Se declaneaz
Se declaneaz
Se declaneaz
la click n control
cnd controlul primete focusul
cnd focusul prsete controlul
cnd proprietatea Text se schimb.
2.
ID-lit
Parola:
L ..................... ............
r------------------- ---------- 1
CNP:
| Autentificare |
3.
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 Properties setai cmpul Name la valoarea
TextBoxEx. n felul acesta, ai modificat numele clasei formei, care iniial
era Forml. Facei click drept n SolutionExplorer pe numele formei i
alegei View Code. n constructorul clasei introducei urmtoarele:
public TextBoxEx()
// 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 Aut en tificare sunt iniial invizibile
cnpLabel.Visible
= false;
cnpTextBox.Visible = false;
autentifButton.Visible = false;
}
5.
ID-ului
introdus,
tratai
evenimentul
{
// 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 PreviewKeyDown pentru verificarea parolei:
private void parolaTextBox_PreviewKeyDown
(object sender, PreviewKeyDownEventArgs e)
{
// Dac tasta apsat este Enter
if (e.KeyCode == Keys.Enter)
Capitolul 7.
157
{
// Eticheta i controlul de tip text
// pentru CNP devin vizibile
cnpLabel.Visible = true;
cnpTextBox.Visible = true;
// TextBox-ul pentru CNP primete focusul
cnpTextBox.Focus();
// Butonul devine vizibil pe form
autentifButton.Visible = true;
}
else
{
MessageBox.Show("Parola incorecta!");
// terge textul din control
parolaTextBox.Clear();
}
}
}
7.
}
8.
{
// Dac lungimea CNP este incorect
if (cnpTextBox.Text.Length != 13)
{
MessageBox.Show("CNP incorect!");
// Se terge textul din control
cnpTextBox.Clear();
158
}
9.
Utilizatorul va completa primul cmp de text cu ID-ul loner, dup care va apsa
Tab, al doilea cmp cu parola parola, dup care apas Enter, 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:
De retinut:
Capitolul 7.
159
ECemente de StiC
Este recomandabil ca n aplicaiile n care folosii mai multe controale, s
introducei propriile nume pentru referine i tipuri. Numele trebuie s fie sugestive,
adic s indice menirea i tipul controlului. Exemplu: idTextBox,
parolaTextBox, etc. Numele claselor trebuie s nceap cu liter mare, de
exemplu TextBoxExample. n felul acesta vei distinge uor referinele i tipurile.
Focusul Controalelor
Controlul care primete intrrile de la tastatur este cel care are focusul'.
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 Tablndex 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.
-V:;
II
A re "fo c u s "
Figura 7.1 F o cu s
Figura 7.2
F o cu su l la ru lare
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.
Capitolul 7.
161
Anchor
Backgrounglmage
1ClientSize
ContextMenu
Text
Metode:
FindForm()
Hide ()
Show()
Evenimente:
C l ic k
MenuActivate
iLeave
TextChanged
Aplicaia M e n u E x a m p le
Proiectul pe care l vom realiza pentru acomodarea cu cele dou controale
implementeaz:
Un editor de text rudimentar cu ajutorul unui control TextBox.
* Operaiile cut/copy/paste . Aceste sunt accesibile att dintr-un meniu ct
i dintr-un meniu contextual.
Urmai paii:
1.
2.
3.
Facei click pe caseta controlului, acolo unde scrie Type Here, i creai un
prim meniu numit Fiier, cu opiunile Nou i Ieire:
4.
Capitolul 7.
5.
163
face din Properties sau mai simplu cu ajutorul meniului contextual care
apare prin click pe sgeata din colul dreapta sus a controlului:
7.
8.
B M
Normal
contextM enuStH v
El (Applicationsetting!
]j
El (DataBindings)
Fiier
Editare
Decupeaz
Lipete
Capitolul 7.
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
nstane ale clasei Form.
DialogResult
Modal
Size
A c t i v a t e ()
Close ()
Invalidate()
Show()
ShowDialog()
Text
Metode:
formei,
fapt
care
Evenimente:
Closing
Load
Crearea formelor
1. Crearea programatic a formelor
n mod programatic, o form se creaz foarte simplu:
Form f = new Form();
f.Show();
/ / S e instaniaz forma
// 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 .Show();
2.
La crearea unui nou proiect de tip Windows Forms, mediul integrat genereaz
o clas cu numele implicit Forml, iar aceast clas se instaniaz n Main ():
Application.Run(new Forml());
Refere
Rebuild
ffl- S B Form l!
!
ffl-
Form2|
;.~~t
: 23
jij
Publish,,,
Add
Add Reference.,,
New Folder
User C ontrol,.,
Debug
Ca variant alternativ, click drept pe numele proiectului, alegei Add, apoi New
Item....
Capitolul 1.
167
n fereastra Add New Item - [nume proiect] selectai iconul Windows Form i
introducei un nume pentru noua form:
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 Cancel). Acest tip de fereastr dialog nu permite utilizatorului s
acceseze alte ferestre ale aplicaiei pn cnd dialogul nu este nchis. De
exemplu, n Microsoft 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 dialog modal.
Un dialog modal este o form care se deschide cu metoda showDialog ():
class Forma : Form
{
// membrii clasei
1
Forma f = new Forma();
f .ShowDialog();
Aplicaia D ia lo g M o d a l
Realizm un proiect de tip consol care lanseaz o form ca dialog modal.
Urmai paii:
1.
2.
n panoul dialogului New Project selectai Empty Project, iar n caseta text
Name, introducei numele proiectului: DialogModal.
3.
4. n dialogul Add New Item, selectai iconul Code File, apoi n caseta Name,
introducei numele fiierului: Modal.cs.
5.
: Form
{
}
class P o gram
{
p u b l i c static v o i d Main()
{
Forma f = new F o r m a Q ;
// Instaniere
// Lanseaz aplicaia
}
}
6.
References:
Capitolul 7.
iW ; I I 181 g 8
UlSjl
:jp
Stfi
A J
H-
169
. 5 ! D ia l o g M o d a l l
a -
i:J Modal,cs i
Add Reference,,,
Add Service Reference..
7.
System.Windows.Forms:
Component Name -*
System.Transactions
System,Web
System, Web.Extensions
System. Web, Extensions. Design
System.Web.Mobile
System. Web. RegularExpressions
; System.Web.Services
System,Windows,Forms
System, Windows, Presentation
System. Workflow, Activities
System. Workflow.ComponentModel
System. W orkflow. Runtime
System. WorkflowServices
System, Xml
i Sv^hftm.Xml.l inn
...
;
;:.
_ i;
'..... ; .
Version
Runtime
|.A 1
2.0.0.0
2.0.0.0
3.5.0.0
3,5.0.0
2,0.0.0
2.0,0.0
2.0.0.0
v2 ,0.50727
v2 .0,50727
v2 ,0.50727
v2 .0.50727
v2 .0.50727
V2.0.50727
v 2 .0.50727
j i
ji
M
i g
3.5.0,0
3.0,0,0
3.0.0.0
3,0,0,0
3.5.0.0
2,0.0.0
3.5.0.0
v 2 ,0.50727
V2.0.50727
v 2 .0.50727
v 2 .0.50727
v 2 .0.50727
v 2 .0.50727
v ? .n .50727
c
c
C 5 li
c~
c
c
r iL
>
8.
c
c
c
c
c
0K....... l l
CanCel
170
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 toolboxurile din Paint sau Word, sau chiar Toolbox din Visual C# Express 2008.
Afiarea se face cu metoda Show(); La nchiderea unei forme cu Close (),
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 o d a lD ia lo g E x a m p le
Descrierea aplicaiei:
>
>
>
Urmai paii:
1.
2.
Capitolul 7.
4.
171
6.
1
7.
{
// Salvm textul introdus n control,
item = textBoxl.Text.Trim();
// nchidem forma Form2.
Close();
}
8. Dorim ca Form2 s se nchid i la apsarea tastei Enter. Tratm
{
// Dac tasta apsat are codul tastei Enter
if (e.KeyCode == Keys.Enter)
{
item = textBoxl.Text.Trim(); // Memorm textul
Close ();
// nchidem forma
}
}
{
f = new Form2();
// Crem forma
f .ShowDialog();
if ( f.Item != "")
{
// 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();
Capitolul 7.
173
Mo:
IMPORTANT!
Cnd apelai Close () pentru un dialog modal, fereastra nu se distruge ci
revine invizibil. Aceasta, deoarece dup nchiderea ferestrei, avei de regul
-evoie de membrii clasei, ca n aplicaia de fa:
f.ShowDialog();
// 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 retinut:
Butoane de validare
d a t e l o r
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.
3entru aceasta, are nevoie de dou butoane, s le spunem OK i Cancel. Evident,
= new Button();
= new Button();
"OK";
// Poate fi i alt etichet
"Cancel";
// Poate fi i alt etichet
{
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 OK sau cu Cancel ? 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 Cancel, forma
se distruge mpreun cu toate controalele i datele reinute n membrii clasei.
Pentru edificare, vom realiza un mic proiect de tip Windows Forms.
Aplicaia O kC an ce!
Aplicaia are dou butoane, cu etichetele OK i Cancel. Primului buton i se
atribuie rolul de validare a datelor, iar celuilalt de renunare. Amndou nchid
forma. Se afieaz cte un message box la nchiderea formei pentru fiecare caz.
Capitolul 7.
175
{
// Seteaz buttonl s returneze OK la click
buttonl.DialogResult = DialogResult.OK;
// Seteaz button2 s returneze Cancel la click
button2.DialogResult = DialogResult.Cancel;
}
6. Tratm evenimentul Click pentru butonul formei Forml. Facei dublu click
pe buton. n metoda handler, introducei codul evideniat n Bold:
private void buttonl_Click(object sender, EventArgs e)
{
Form2 f = new Form2 () ;
DialogResult rez = .ShowDialog();
switch (rez)
{
case DialogResult.OK;
MessageBox.Show("Dialog inchis cu OK");
break;
176
case DialogResult.Cancel:
MessageBox.Show("Dialog inchis cu Cancel");
break;
}
1
La execuie, nainte de nchiderea Form2, avem:
gjj
De rein ut:
Putei desemna butoane care returneaz valori egale cu cele ale unor
membri ai enumerrii DialogResult.
Valoarea returnat la acionarea click asupra unui asemenea buton este
aceeai pe care o returneaz metoda ShowDialogO . Acest lucru
permite ca ulterior nchiderii formei s se dirijeze fluxul de execuie a,
programului n funcie de rezultatul ntors de form.
Probleme propuse
1.
titlu,
butoane) cu
Capitolul 7.
177
Dialoguri predefinite
.NET ofer cteva dialoguri predefinite pe care le putei invoca n aplicaii.
Dialogurile sunt forme. Cnd n Notepad sau Microsoft Word acionai File ->
Open, File -> Save As sau File -> Page Setup, invocai de fapt unul dintre
dialogurile standard Windows.
Clasele .NET care reprezint dialogurile predefinite sunt: MessageBox,
OpenFileDiaiog, SaveFileDialog, FontDialog, ColorDialog, PageSetupDialog,
PrintDialog i PrintPreviewDialog.
Toate aceste dialoguri sunt dialoguri modale.
178
Capitolul 7.
179
if (openFileDialog.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Cod care deschide fiierul
}
openFileDialog este o referin la un obiect de tip OpenFileDialog. Referina
Observaie:
Toate cele apte dialoguri predefinite sunt dialoguri modale, deoarece
utilizeaz metoda ShowDialog (). Un dialog modal ntrerupe aplicaia, iar
utilizatorul nu poate continua pn n momentul n care dialogul a fost nchis.
2.
3.
Fiier | Format
|
Deschide
Salveasa ca
Setare pagina
Imprimare
Prevteualisare
j
Type Hei e
4.
5.
6.
{
// Titlul dialogului
openFileDialogl.Title = "Deschide Fiier";
// Seteaz tipurile de fiiere care apar
// n comhobox-ul "Files of Type"
openFileDialogl.Filter =
"Fiiere Rich Text (*.rtf)|*.rtf|Fiiere Text (*.txt)|*.txt";
/ / n combobox-ul File Name nu vrem s apar la
// deschiderea dialogului nici un nume de fiier
openFileDialogl.FileName = "";
Capitolul 7.
181
{
// Cod care deschide fiierul
}
7.
{
// 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.
{
// Se preiau setrile din printDocumentl
pageSetupDialogl.Document = printDocumentl;
// Setrile de pagin
pageSetupDialogl.PageSettings =
printDocumentl.DefaultPageSettings;
182
9.
}
Facei dublu click pe opiunea imprimare. n handler scriei codul:
private void imprimareToolStripMenuItem_Click
(object sender, EventArgs e)
// Se preiau setrile de printare din
// obiectul de tip PrintDocument
printDialogl.Document = printDocumentl;
// Se deschide dialogul PrintDialog
if (printDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Starteaz procesul de printare
printDocumentl.Print();
// Cod care transform documentul
// n imagine i l printeaz
//
...
}
}
10. Dublu click pe opiunea Previzualizare. n handler, scriei codul:
private void previzualizareToolStripMenuItem Click
(object sender, EventArgs e)
{
if (printPreviewDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Cod care afieaz documentul in dialog
}
}
Capitolul 7.
183
{
// Se deschide dialogul FontDialog
if (fontDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Cod care reafieaz documentul cu
// fontul ales de utilizator
}
}
12. Dublu click pe opiunea Culori. n handler-ul evenimentului, scriei codul:
private void culoriToolStripMenuItem_Click
(object sender, EventArgs e)
// Se deschide dialogul ColorDialog
if (colorDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
// Cod care actualizeaz culorile in document
}
13. Compilai i rulai cu F5.
Basic colors:
m r r m r ss r
m r m m r~ m b h
m r
m M M u m
Custom colors:
OK
||
Cancel
Comentarii:
Proprietatea Filter este comun dialogurilor OpenFileDialog i
SaveAsDialog, 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 (*.rtf)|*.rtf|Fiiere Text (*.txt)|*.txt";
Files of type:
Cancel
Not:
n ce privete printarea efectiv a unui document, aceasta se face prin
apelul metodei Print () a clasei PrintDocument. Clasa PrintDocument este
definit n spaiul de nume System.Drawing.Printing. 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 PrintDocument 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, metodelor i evenimentelor lor, dar i cu exemple de cod care v
pot ajuta. Vei descoperi foarte repede membrii ai claselor care v pot fi utili.
Reamintim locaia Bibliotecii de Clase: Help -> Contents -> .NET
Framework SDK -> .NET Framework Class Library.
Capitolul 7.
185
Aplicaia M d iE x a m p le
Aplicaia implementeaz:
>
>
>
>
Urmai paii:
1.
2.
3.
4.
186
{
// 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 .Show();
1
6.
Capitolul 7.
187
{
CreateChild();
}
7. Acum tratm evenimentele Click 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 ;
CreateChild);
{
// Dac exist o fereastr copil activ,
// aceasta se minimizeaz
if (ActiveMdiChild != nuli)
ActiveMdiChild.WindowState =
FormWindowState.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)
ActiveMdiChild.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 T i l e pe orizontal
this.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
this.LayoutMdi(MdiLayout.Cascade);
}
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 Propertie apsai butonul
Events (fulgerul). Acionai dublu click pe evenimentul FormClosing. n
metoda de tratare a evenimentului, scrii codul evideniat n Bold:
private void Forml_FormClosing(object sender,
FormClosingEventArgs e)
{
DialogResult result = MessageBox.Show(
"Eti sigur ca vrei sa parasesti aplicaia?",
"Avertizare", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
Capitolul 7.
}
16. Compilai i rulai aplicaia cu F5.
Cteva capturi de ecran din timpul rulrii:
a) Dup deschiderea ctorva ferestre copil:
b) Aranjare T ile :
189
190
c)
De retinut:
Capitolul 7.
191
Probleme propuse:
Controlul RichTextBox
RichTextBox deriv direct din clasa TextBoxBase, la fel ca i TextBox. n
vreme ce un TextBox se utilizeaz pentru a introduce secvene scurte de
caractere de la tastatur, un RichTextBox se utilizeaz cu precdere ca editor de
text.
Controlul are toate facilitile unui TextBox, 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 TextBox poate fi nlocuit fr
modificri majore de cod cu un control RichTextBox.
n aplicaia care urmeaz vom utiliza pentru prima oar i o bar de
instrum ente, cu ajutorul controlului ToolStrip. 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:
:
* io r b i u m
_....
i...------.--------
Aplicaia R ic h T e x tB o x E xa m p le
Vom realiza un mic editor de text, asemntor celui creat n subcapitolul
TextBox. Controlul care afieaz textul va fi de data aceasta un RichTextBox.
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.
2.
3.
Nou
Deschide
; Salveaza Ca
"
i
Ieire
4.
__ __ ___
,1
Capitolul 7.
193
7.
Click drept pe fiecare buton din ToolStrip i alegei Set Image. n dialogul
Select Resource, apsai butonul Import. Vei lipi astfel pe fiecare buton
imaginea dorit:
View Code
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 Properties atribuii
proprietii Text un text scurt, reprezentnd rolul butonului:
Fiier
'O
Format
M m
Pi ij
tit':' U
| Alege un Font|
9.
10. Vom trata evenimentul Click pentru fiecare dintre opiunile meniului, dar i
pentru butoanele din ToolStrip. Dublu click pe opiunea Nou. n corpul
handler-ului de eveniment, scriei codul:
{
// 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 Fiierul. 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 Fiierul'. Scriei acelai cod.
13. Dublu click pe opiunea Ieire. n corpul handler-ului adugai codul:
Application.Exit();
{
if (fontDialogl.ShowDialog()
Capitolul 7.
195
System.Windows.Forms.DialogResult.OK)
{
// Poriunea selectat din text preia
// caracteristicile alese de ctre utilizator
richTextBoxl.SelectionFont =
fontDialogl.Font;
}
}
Dublu click pe butonul cu textul Alege un Fonf. Scriei acelai cod.
15. Dublu click pe opiunea de meniu Culoare. Handler-ul evenimentului
trebuie este:
private void culoareToolStripMenuItem__Click
(objectsender, EventArgs e)
{
if (colorDialogl.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
richTextBoxl.SelectionColor =
colorDialogl.Color;
}
}
Dublu click pe butonul cu textul Alege o Culoare". Scriei acelai cod.
16. Selectai ultimul buton din ToolStrip, cu textul Bullets". n fereastra
Properties, setai proprietatea Name la valoarea bulletButton i
proprietatea CheckOnClick la valoarea true. Dublu click pe buton
pentru a trata evenimentul Click. n metoda handler scriei:
private
void
EventArgs e)
toolStripButton9_Click(object
{
// Dac butonul era apsat atunci textului
// selectat nu i se aplic stilul bullet
if ( bulletButton.Checked )
richTextBoxl.SelectionBullet = false;
else
richTextBoxl.SelectionBullet = true;
}
17. Compilai i lansai cu F5.
sender,
a
F iier
F o rm a t
...................... ....................
V-
I :=
. J..... _
Font:
Size:
F o nt style:
i i i :
_ M ila n o LET
1T r MisterFarl RT
! Ita lic
: R egu lar
B Ita lic
i RnlH
OK
1 4
!
16
IR
C a n ce l
Observaie:
{
richTextBoxl.LoadFile(openFileDialogl.FileName);
}
catch (System.Exception e)
{
MessageBox.Show(e.Message);
Controlul ToolTip
ToolTip se utilizeaz pentru afiarea unor mesaje de informare sau de
avertizare, atunci cnd utilizatorul plaseaz cursorul desupra unui control. O
Capitolul 7.
197
singur instan a clasei este suficient pentru a furniza texte de informare pentru
toate controalele unei forme.
Exemplu:
ToolTip t = new ToolTip();
Button
b = new Button();
ComboBox c = new ComboBox();
t. SetToolTip(b, "Valideaza datele");
t .SetToolTip(c, "Lista elevilor din clasa a XII-a B );
Dac dorii stiluri i afiri diferite pe aceeai form, vei utiliza mai multe controale
ToolTip.
IsBallon
ToolTipIcon
ToolTipTitle
Metode:
H id e ()
Show()
RemoveA l l ()
Evenimente:
Popup
Aplicaia T o o lT ip E x a m p le
n proiectul de fa se folosete acelai ToolTip pentru mai multe controale
de pe aceeai form. Se utilizeaz designer-ul pentru toate aciunile necesare.
1.
198
Nume:
Adresa:
Studii
O
Medii
Superioare
Cstorit
OK
,--------------Cancel
3.
4.
5.
6.
Nume:
Adresa:
Nume:
Studii
Studii
Medii
Superioare
OK
Medii
(*}
Superioare
/ ] C af-a frnrir-----------------
Cancel
QK
-------------------
Capitolul 7.
199
De retinut:
>
>
Controlul NotifyIcon
Formele, ca de altfel i alte controale, motenesc metoda H id e () 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 Click sau Doubleclick 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.
Visible
Evenimente:
C lic k
D o u b le c lic k
Aplicaia N o tify lc o n E xa m p le
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 click
ntr-un meniu de context.
Urmai paii:
1.
2.
A cunde Fotma
3.
Capitolul 7.
201
(AppIicationSettings)
(Name)
n o tify lc o n l
BalloonTipIcon
None
BalloonTipText
BalIoonTipTitle
El ContextMenuStrip
GenerateMember
contextM enuStrip 1
True
I E S I (Ic o n )
Modifiers
Private
Tag
5.
Text
Visible
True
{
// Ascunde forma aplicaiei
this.Hide();
{
// Ascunde forma aplicaiei
this.Hide();
202
{
this.Visible = true;
}
8.
}
9.
}
10. Acionai dublu click pe opiunea Reafiseaza. n editor scriei codul:
private void reafiseazaToolStripMenuItem_Click(
object sender, EventArgs e)
{
this.Visible = true;
Capitolul 7.
203
Iconul de
notificare
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 retinut:
*
Forituri
Fonturile nu sunt controale .NET. Clasa Font este definit n spaiul de
nume System.Drawing. Un obiect de tip Font ncapsuleaz un format particular
Exemplu:
Setm fontul afiat de ctre o etichet:
Label e = new L a b e l ();
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 poriune de text conine stilurile Bold, Italic i Underline.
Aplicaia F o n tS ty le E x am p le
Proiectul
RichTextBox:
introduce
stilurile
Bold,
Italic,
Underline,
ntr-un
control
1.
2.
3.
4.
Capitolul 7.
205
{
Font vechiulFont, noulFont;
// 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.
this.richTextBoxl.SelectionFont = noulFont;
this.richTextBoxl.Focus() ;
5.
6.
7.
IB H iilW M M I
|gMl gtlJMR
Bold
Italic
Underline
E p rie te n u l m e u a c e la
c a re m a
vorbete de bine
pe la spate.
Thomas Fuller
li-i drumul o a re ?
parc-sia aman
Se marlf-o vrjitoare ?
l ngroappe Satan ?
Aleksandr Puskin
n c o tro
Z b ia r
-i
206
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 FontStyle.
( Or logic pe bit!' (|) adaug un stil nou, iar And logic pe bit!', 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 System.Drawing.Text se obin fonturile instalate n sistem, astfel:
using System.Drawing.Text;
InstalledFontCollection fnt = new InstalledFontCollection();
Desenarea fonturilor
.NET Framework 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 Drawstring (). 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
Capitolul 7.
207
unei forme, atunci cel mai bun moment pentru desenare este acela al desenrii
*'ormei i vom trata evenimentul Paint al formei.
Aplicaia F o n tD ra w in g E x a m p le
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.
2.
3.
{
// 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.Drawing.Text;
5.
{
// Invalideaz suprafaa formei, fapt
// care cauzeaz redesenarea acesteia
this.Invalidate();
}
6.
208
{
try
{
// Deseneaz fontul pe suprafaa formei
e .Graphics.DrawString(comboBoxl.Text,
new Font(comboBoxl.Text, 40),
Brushes.Black, 10, 50);
}
catch (ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
}
7.
J o k e rm a n LE T
K a r tik a
L a B am ba LET
L a lh a
L u c id a C o n s o le
L u c id a S a n s U n ic o d e
M angal
TabControl
Un TabControl 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-ul dorit sau se poate face programatic. Paginile tab suport alte
controale, n mod similar formelor. Astfel, un TabControl poate constitui o
alternativ unei afiri succesive a mai multor forme.
Capitolul 7.
S e le c te d ln d e x
S e le c t e d T a b
TabCount
TabPages
209
Metode:
G e t C o n t r o l()
G e tlte m s ()
Evenimente:
S e le c t e d
S e le c t e d ln d e x C h a n g e d
Aplicaia T a b C o n tro lE x am p le
Aplicaia pe care o propunem utilizeaz un TabControl pentru afiarea
imaginilor. 7ab-urile controlului se adaug runtime, in momentul n care se ncarc
o imagine de pe disc. Operaiile se execut la apsarea butoanelor unui control
ToolStrip. Acestea sunt:
>
>
>
>
>
Urmai paii:
1. Creai un nou proiect de tip
TabControlExample.
2.
3.
W in d o w s F o rm s A p p lic a tio n ,
cu numele
210
. d o s e Ai! [
"4L~ 5 ] : ViewCocle
[J }'
Set Im a ge...
Enabled
Alignment
!J l
->----
DisplayStyle
None
C onve rt To
Text
In s e rt
Image
Im ageA ndText
Select
dV
Cut
Copy
5.
6.
{ '\ V
};
Capitolul 7.
7.
211
Tratm evenimentul Click pentru butonul Add Image. Acionai dublu click
pe buton. n handler-ul de eveniment, scriei codul evideniat n Bold:
private void toolStripButtonl_Click(object sender,
string] aux;
string fullPath; // Calea pn la fiierul imagine
string imgName;
// Numele fiierului imagine
{
// Obinem calea pn la fiier
fullPath = openFileDialogl.FileName;
10. Tratm evenimentul Click pentru butonul Close. Facei dublu click pe
buton. n metoda de tratare, scriei codul evideniat n Bold:
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);
}
}
Capitolul 7.
213
11. Tratm evenimentul Click pentru butonul Close AII. Facei dublu click pe
buton. n metoda de tratare, scriei codul evideniat n Bold:
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 fad
ul selectat, iar cu Close AII se nchid toate paginile.
Probleme propuse
1.
2.
214
listBoxl
ListBox Tasks
ii
Cancel
Exemplu:
com boBox.Ite 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.
Exemplu:
comboBox. B e g in U p d a te ( ) ;
/ / Controlul nu se mai redeseneaz
f o r ( i n t i = 0 ; i < 200; i+ + )
com boBox.Ite m s .A d d ( " I te m u l " + i ) ;
comboBox. E n d U p d a te ( ) ;
Capitolul 7.
215
Listele pot prelua itemi. Sursele de date pot fi tablouri, colecii, DafaSef-uri.
Exemplu:
stringf] copii = { "Ionel", "Viorel", "Alinei", "Dorel" };
checkedListBox.DataSource = copii;
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 ListBox, ComboBox i CheckedListBox.
1.
2.
3.
Sub primele dou controale de tip list plasai cte un buton. Sub controlul
de tip CheckListBox plasai dou butoane. Stabilii valorile proprietilor
Mame
ale
butoanelor
astfel:
listButton,
comboButton,
checkListButtonl i checkListButton2, iar valorile proprietilor
Text, aa cum se vede n figur:
,,,..
ListBox
>V
ComboBox
CheckedListBox
. r ~ ......... ..... ~ 4
Incarca ComboBox
Incarca o lista
Inca rca alta lista
4.
{
// Un tablou de referine la obiecte de tip string
string] copii = { "Ionel", "Viorel", "Alinei",
"Dorel" };
// Sursa de date este tabloul
checkedListBoxl.DataSource = copii;
}
5.
}
}
Vom defini de asemenea un cmp privat el n clasa Forml, de tip referin
la un tablou de obiecte de tip Elev:
private Elev[] e l ;
6.
Capitolul 7.
217
}
7.
{
/* 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();
{
stringf] copii = { "Ionel", "Viorel", "Alinei",
"Dorel" };
checkedListBoxl.DataSource = copii;
}
9.
{
// Crem obiectele care se insereaz n list
el = new Elev[] { new Elev("marius"),
new Elev("lenuta")};
218
ListBox
CheckedListBox
ComboBox
ii.............
Ionel
Hemul 0
Hemul 1
Hemul 2
~ 7
|| | Viorel
j| | Alinei
f~| Dorel
m m sm
Incarca ListBox
Hemul 5
Hemul 6
Hemul 7
Incarca o lista
V
TrackBar
TrackBar:
Capitolul 7.
219
NumericUpDown
NumericUpDown:
!fl
DomainUpDown
D omainU pD own:
Este similar cu un ListBox n aceea c ofer o list de opiuni ntre care utilizatorul
poate alege. Diferena fa de ListBox 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.
Aplicaia O p a c ity
Vom utiliza controalele TrackBar, NumericUpDown i DomainUpDown
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 ie utilizm pe toate.
1. Creai un nou proiect de tip Windows Forms Application, cu numele
Opacity.
2.
Revenire
NumericUpDown:
:0
DomainUpDown:
!0pacitate100%
TrackBar:
v*
3.
4.
{
// Odat cu creterea valorii Value de la 0
// 10 , opacitatea formei trebuie s scad
this.Opacity = 1 - (double)trackBarl.Value / 10;
5.
}
Tratm
evenimentul
SelectedlndexChanged
pentru
controlul
DomainUpDown, 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.
Capitolul 7.
221
{
// Value este valoarea afiat n control
this.Opacity - 1 - (double)numericUpDownl.Value/10;
}
7.
}
8.
t.
ca|'ipiori 2003
CjImageTest
c n u t 2004
caeipion 200S
Ol ca'ipion 2006
?j magineAudoEuIulia
Revenire
a JAVA 1.3
Oi OJMPION 200?
O) ca ipiarr 2006
0 G 'te NumerieUpDown:
01 G le-STL
a Ci t i OcmainUpDown:
a cpi
a G -VORKS
a cy jwin
a di; stra TtackBat:
ea e f Life...........
a
a
a
ppr
gard
jO a v a f
3pAA_Tuteriai_5UN
PiSliavadoc
2, j JavaExampiesZ
Clpacifale 602
^Javaexe
LOlia-'axrrti
........... ,:--3BJWer
domainUpDownl.
............. a n a ...........
222
2.
3.
4.
}
5.
}
6.
Panoul e transparent
Forma e transparent
Capitolul 7.
223
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 le . 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 Value 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 PerformStep () incrementai valoarea barei de
progres cu valoarea step.
Exemplu 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;
or (int i = 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 Controlul Timer ilustreaz i
utilizarea unui progress bar.
Controlul Timer
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.
Capitolul 7.
3.
225
I n c r e m e n t a r e la 2 s e c u n d e
S ta r t
S to p
System.Timers.Timer
A fi e a z o r a e x a c t
Ia b e l5
4.
5.
Components
t Printing
Dialogs
. - General
There are no usable controls in this group. Drag
an item onto this text to add it to the toolbox.
|| v I List View
Show AS
I
;
.....
7. Tragei noul Timer pe suprafaa formei. n
designer tray, selectai referina timerl. n
panoul Properties, schimbai numele referinei la systemTimer, setai
Choose Items..,
226
{
time += 2;
{
// oprim timer-ul i bara de progres
winTimer.Stop();
progressBarl.Enabled = false; // oprim
}
}
11. Tratm evenimentul Click 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
{
/ / s e fac reiniializri
time = 0;
progressBarl.Value = 0;
}
}
12. Tratm evenimentul Click pentru butonul Stop. Facei dublu click pe buton.
Introducei codul:
Capitolul 7.
227
{
winTimer.Stop () ;
// Oprir cronometrul
progressBarl.Enabled = false; // Oprim p r o g r e s s b a r
if (nrTick == 20)
{
nrTick = 0;
progressBarl.Value = 0;
}
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.Timers.ElapsedEventArgs e)
{
// Proprietatea Now a clasei DateTime, returnez
// ora exact
label5.Text =System.DateTime.N o w .ToLongTimeString();
}
14. Compilai i rulai aplicaia cu F5.
Captur de ecran la execuie:
...... i?-.rJd.: ,_i
1 2
i i i i l i vi*
I n c r e m e n t a r e la 2 s e c u n d e
>' i |
S ta r t
S to p
A fi e a z o ra e x a c t
14:00:31
228
Capitolul 7.
229
>
Backgroundl m a g e L a y o u t
Are valorile posibile: None, Tile, Center, Strech i Zoom. De exemplu,
mai sus, pentru CheckBox, i RadioButton am ales Center, iar pentru
GrupBox valoarea Tile.
ImageAllign
Label-urile nu suport Backgroundlmage deci utilizai Image pentru
A u t oSize
T e xtAllign
Clasa Image
.NET definete clasa Image n spaiul de nume System.Drawing, 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 ():
Exemplu:
Image im = Image .FromFile (
Path.Combine(Application.StartupPath, "foto.gif"));
Label lbl = new lbl Labei(); // 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 folderul 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
F r om St re am () ncarc imagini de diferite tipuri nu numai n formatele standard
.GIF sau .BMP. Creaz un stream din care putei descrca imaginea. Sream-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;
// URL
// Sunt necesare obiectele w r q i wrs pentru crearea
// stream-ului
We bR eq u e s t w r q = W e b R e q u e s t .C r e a t e ( s ) ;
We bR e s p o n s e wrs = w r q . G e t R e s p o n s e ();
St ream 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
Controlul PictureBox
PictureBox este un control aflat la ndemn n Toolbox. E folosit pentru
afiarea imaginilor grafice, obinute din fiiere JPEG, GIF, BMP, PNG, iconuri sau
metafiiere.
Prezentm civa membri reprezentativi ai clasei PictureBox.
Proprieti
Image
SizeMode
ClientSize
Im ageLocation
Metode
L o a d ()
S e t B o u n d s ()
Evenimente
Click
Paint
Cl ie nt S i z e C h a n g e d
Capitolul 7.
231
Aplicaia Im a g e R es o u rc e E x a m p le
Proiectul va fi unul simplu: pe o form, avem un control PictureBox.
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 Windows Forms Application, cu numele
ImageResourceExample.
16. Aducei din Toolbox pe suprafaa formei un control de tip PictureBox i
dou butoane.
17. Selectai controlul PictureBox. n panoul Properties, setai pentru
proprietatea SizeMode valoarea Zoom. Aceasta permite controlului s se
redimensioneze odat cu imaginea.
18. Selectai pe rnd cele dou butoane i stabilii pentru proprietatea Text,
valorile Zoomln, respectiv ZoomOut:
Application
. ;al Images
L?J?cj
Build Events
jH
Debug
Resources
Settings
Strings
Add Resource
Ctrl+1
Images
Ctrl+2
Icons
Ctrl+3
Audio
Ctrl-4-4
Files
Ctrl+5
Other
Ctrl+6
232
Application
. . . . .
J Add Resource -
iT>
Build
New Image
Debug
j
Resources*
Form 1. cs
i
j j Images Q Add Resource ?
Application
l! |
ij
! S
I|
i
j
i
j
: Build Events
|
1 ij
i 11
I M
1 ii
1
___ i
Debug
!
i
Resources*
f-----------------------
Settings
i
i
j i i
S j]
S) 3 $ Properties
i
{&
\S M
References
Resources
j i j actori,bmp
0 - ilF o r m l.e s
jb ] Forml.Designer.es
jfi) Forml.resx
':J3 Program.es
actori
j
24. Tratm evenimentul Click 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, EventArgs e)
{
zoom = 2;
Capitolul 7.
233
De retinut:
9
234
Resursa pisica este un tip nou creat, pe baza unei imagini obinute dintr-un fiier
care se numea de exemplu pisica.bmp.
Clasa ImageList
ImageList este un control care ncapsuleaz o colecie de imagini sau iconuri. Imaginile se folosesc de ctre alte controale, cum este Listview, TreeView,
sau ToolStrip. Principalii membrii ai clasei sunt:
Proprieti
Images
ImageSize
ColorDepth
Metode
Draw()
Capitolul 7.
235
A p lic a ia Im a g e L is tE x a m p le
2.
3.
4.
5.
'
I mageLi st Tasks
{ d P imageListl
.................... .......... Image Size
32; 32
8.
"
Choose images.........................
236
Members:
caine.jpg properties:
0
1 E 3
g ira fa .jp g
2 F a
g o rila .jp g
3 E 3
p is ic a .jp g
i i i
B Mise
0
j; ; . HcrizoritaiRescbt
............
Name
caine.jpg
fc p ixe ro m ^ i
151 f '
'
. Formas32fcppA?gb
7 1
Iii}.1; R3ArOt'IYlr
MemaryBmp
5 O
0 :
u rs .jp g
v u ltu r .jp g
0 _.::e
..... ................. i
9 .,
Add
Remove
]
OK
9.
Cancel
10. Vom trata evenimentul Click pentru buton. Acionai dublu click pe
suprafaa lui. Scriei codul evideniat cu Bold, 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.
Capitolul 7.
237
De retinut:
Controlul ListView
ListView este un control complex, destinat afirii unei liste de itemi.
Panoul din dreapta al aplicaiei Windows Explorer implementeaz un
ListView. 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 ListView.
L a r g e lc o n
238
Smalllcon
List
Details
Tile
IMPORTANT!
Fiecare item ntr-un control ListView, este o instan a clasei ListViewltem.
Items
Collumns
View
LargelmageList
SmallImageList
MultiSelect
Metode:
Clear ()
BeginUpdate()
EndUpdate()
Capitolul 7.
239
Evenimente:
ColumnClick
SelectedlndexChanged
Aplicaia L istV ie w E x a m p le
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.
2.
3.
4.
SP1imageListl
......................... m Im ag e L is t Tasks
j ifjP imageList2
Image Size
i S ill
Image Bit Depth
Error List
Depth32Bit
v '
Choose images
6.
7.
{
// Controlul listViewl preia coleciile de iconuri
// mici i de iconuri mari
listViewl.SmallImageList = imageListl;
listViewl.LargelmageList = 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
// alini erea orizontal
listViewl.Columns.Add("Crti C#", 150,
HorizontalAlignment.Left);
listViewl.Columns.Add("Autor", 100,
HorizontalAlignment.Left);
listViewl.Columns.Add("Editura", 110,
HorizontalAlignment.Left);
// Adugm primul item n list. Este un obiect de
// tip ListViewItem
ListViewItem itl = new ListViewItem();
// Indexul icon-ului din listlmagel i listlmage2.
// Putei avea mai muli itemi cu acelai index,
// deci cu acelai icon
itl.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.
Capitolul 7.
241
itl.Subitems.Add("Jurgen Bayer");
it l.Subitems.Add("Addison-Wesley 2007");
}
8.
}
9. Acionai dublu click pe radio butonul cu eticheta Tile. n corpul handler-ului
de eveniment, scriei codul:
listViewl.View = View.Tile;
checkBoxl.Enabled = false;
10. Acionai dublu click pe radio butonul cu eticheta Small Icons. n corpul
handler-u\u\ de eveniment, scriei codul:
listViewl.View = View.SmallIcon;
checkBoxl.Enabled = false;1
11. Acionai dublu click pe radio butonul cu eticheta List. n corpul hand/er-ului
de eveniment, scriei:
242
{
// Dac tocmai s-a selectat checkbox-ul
if (checkBoxl.Checked)
{
// atunci punem griduri.
listViewl.GridLines = true;
}
else
{
// Dac tocmai s-a deselectat controlul
// scoatem gridurile
listViewl.GridLines = false;
}
13. Acionai dublu click pe butonul Ieire. Tratm evenimentul Click. n corpul
metodei de tratare, scriei:
Application.Exit();
| Visual C8 2008
VisualC8.NET
Visual Studio
2008
v :
,-----
l
lesire
Capitolul 7.
243
Crti Ctt
v sfv
Autor
Editura
Jurgen Bayer
Karli Watson
Addison-Wesley...
WROX 2008
Joseph Mayo
InformIT 2007
Mark Michaellis
Andrew Stellman
InformlT 2007
APRESS 2007
O Tile
Andrew T roelsen
Dirk Frischalowski
APRESS 2007
Addison-Wesley 2...
O Small Icons
James Foxall
InformlT 2008
Lars Powers
Rob Eisenberg
Addison-Wesley 2...
Moduri Afiare
O Large Icons
O List
@ Detail
Addison-Wesley 2... ;
P I Grid
i
!
]
Ieire
Observaii:
ListViewltem: {} p roperties:
_0 I ListViewltem: {}
l l ListViewltem: {}
ListViewltem: {}
....2 j UstVSewItem;
{}
0 m
0
Text
... ...
ToolTipText
U seltem StyleFor True
B Behavior
Group
(none)
Im agelndex
| (none)
S tatelm ag eln d ex I
I (none)
Im ageKey
B Data
5ubltems
(none)
(Collection)
Tag
E Display
IndentC ount
Cancel
n panoul din dreapta, selectai Subitems i apsai butonul din dreapta. n dialogul
ListViewSubitem Collection Editor, adugai pe rnd subitemii necesari pentru
fiecare item:
E
Members:
o m sm m m ssm m m
iJjListViewSubItem: -{Karl Watson}
T j ListViewSubitem: <WROX 2008}
I
[~4~|
HTji .
E l Data
Tag
E Mise
BackColor
E Font
ForeColor
| Window
WindowText
Name
ListViewSubItem3
Text
Beginning C# 2008
Add
Cancel
De retinut:
>
>
>
Capitolul 7.
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 Detail.
2.
3.
4.
Controlul 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 (dubiu click pe
suprafaa ei), apoi scriei codul:
private void Forml_Load(object sender, EventArgs e)
{
// Instaniem un TreeView
TreeView tw = new TreeView();
// Crem un prim nod cu eticheta "Biei"
246
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.Drawing.Size(153, 133);
// Crem un prim nod cu eticheta Baieti
TreeNode tnl = new TreeNode();
tnl.Text = "Baieti";
// Crem un nod child pentru Baieti:
TreeNode tnll;
II Referina tnnl indic nodul nou creat (cu eticheta Marius)
tnll = tnl.Nodes.Add("Marius");
// Nodul M a r i u s va fi printe pentru alte dou noduri:
tnll.Nodes.Add("Profesie");
tnll.Nodes.Add("Hobby");
II Al doilea nod child pentru Baieti:
tnl.Nodes.A d d ("Valentin");
// Adugm nodul Baieti n control:
tw.Nodes.Add(tnl);
Capitolul 7.
//
Crem
al
doilea
rdcin
cu
eticheta
247
Fete :
Adugm
controlul
n
pe
control
form
this.Controls.Add(tw);
B Marius
Profesie
H obby
Valentin
S- Fete
Alina
T eodora
Important:
Metoda A dd() returneaz ntotdeauna o referin la nodul nou creat.
Aceasta nlesnete adugarea de noduri child.
Stabilim
poziia
pe
form
dimensiunea
controlului:
Adugm
control
un
prim
nod:
tw.Nodes.Add("Biei");
// A d u g m s u b n o d u r i l e Marius si Valentin
tw.Nodes[0].Nodes.Add("Marius");
tw.Nodes[0].Nodes.Add("Valentin");
pentru
Biei
248
La execuie se obine :
LabelEdit
ChectcBoxes
SelectedNode
PathSeparator
Capitolul 7.
249
Metode:
CollapseAll ()
BeginUpdate()
EndUpdate()
GetNodeAt()
Evenimente:
BeforeCollapse
Af terCollapse
BeforeExpand
AfterExpand
{
foreach (TreeNode nod in noduri)
{
PrelucrezNod(nod);
ParcurgTreeView(nod.Nodes);
}
}
private void PrelucrezNod(TreeNode nod)
1
// Prelucrarea dorit pentru nod
// Aici, pentru verificare afim doar eticheta
MessageBox.Show(node.Text + "\n");
}
private void buttonl_Click(object sender, EventArgs e)
{
//
ParcurgTreeView(treeViewl.Nodes);
250
De retinut:
2.
3.
Capitolul 7.
4.
251
// Constructoul clasei
{
InitializeComponent();
// Populeaz comboBoxl cu toate drive-urile
DriveInfo[] drives = Drivelnfo.GetDrives();
comboBoxl.Iterns.AddRange(drives);
}
// Cmpuri private. Reprezint caracterul de separare
// a cii de director, respectiv litera discului
private char[] sep = new char[] { '\ \ ' };
private string drvLetter = nuli;
// Deep First n structura de directoare
private void PopulateTreeView(string path,
TreeNode node)
{
stringf] dirs = Directory.GetDirectories(path);
string[] auxs;
foreach (string dir in dirs)
{
auxs = dir.Split(sep);
TreeNode tn =
new TreeNode(auxs[auxs.Length - 1]);
node.Nodes.Add(tn); // Adaug subdirectorul
PopulateTreeView(dir, tn) ;
}
}
6.
{
// Obinem textul itemului selectat n combobox
drvLetter =
comboBoxl.Items[comboBoxl.Selectedlndex].ToString();
// Suspendm redesenarea controlului
treeViewl.BeginUpdate();
// tergem toat colecia de noduri
treeViewl.Nodes.Clear() ;
wm
252
8.
La rulare obinei:
Observaie:
De retinut:
Capitolul 7.
253
Probleme propuse
1.
2.
3.
4.
254
3.
4.
5.
6,
{
// ncarc pagina de la adresa specificat
webBrowserl.Navigate(toolStripTextBoxl.Text);
}
7.
{
// Oprete ncrcarea paginii
webBrowserl.Stop();
Capitolul 7.
8.
255
{
// Revenire la pagin aanterioar
webBrowserl.GoBack();
}
9.
{
// Rencrcarea paginii de la URL-ul curent
webBrowserl.Refresh();
}
10. n progress bar-ul integrat n StatusStrip dorim s vizualizm progresul
ncrcrii paginii. n acest scop, tratm evenimentul ProgressChanged
pentru controlul WebBrowser. Selectai controlul i acionai dublu click pe
acest eveniment n fereastra Properties. Introducei codul:
private void webBrowserl_ProgressChanged(object sender,
WebBrowserProgressChangedEventArgs e)
{
// Seteaz Maximum la numrul total de b y t e s pe
// care l ocup documentul care se descarc
toolStripProgressBarl.Maximum =
(int)e.MaximumProgress;
// Seteaz Value la numrul de b y t e s care au fost
// downloadai pn n prezent
toolStripProgressBarl.Value =
(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
DocumentCompleted declanat de WebBrowser cnd documentul este
complet descrcat. Dublu click pe acest eveniment n Properties. n
metoda de tratare, introducei codul:
private void webBrowserl_DocumentCompleted(
object sender, WebBrowserDocumentCompletedEventArgs e)
{
toolStripProgressBarl.Value =
toolStripProgressBarl.Maximum;
256
Observaii:
Capitolul 7.
257
Aplicaia W in d o w s M e d ia P la y erE x a m p le
Aplicaia utilizeaz componenta Windows Media Player i un control de tip
2.
3.
4.
258
EventArgs e)
{
8.
Capitolul 7.
9.
259
EventArgs e)
{
// Redarea se reia din poziia n care s-a ajuns
// la ultimul apel pause()
w m p .Ctlcontrols.play();
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.
C a p ito lu l 8
Clasa Graphics
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).
DrawArc()
Drawlmage()
DrawLine()
DrawEllipse()
DrawRectangle()
Drawstring()
FillEllipse()
FillRectangle()
Clasa nu rspunde la evenimente findc nu are membri de tip event. Dar folosete
evenimentul Paint al controalelor pentru a desena pe suprafaa lor.
261
Cazul 1.
Creai un proiect nou de tip Windows Forms. Tratm evenimentul Paint al
formei. Selectai forma i n fereastra Properties acionai dublu click pe
evenimentul Paint. Scriei codul:
262
Cazul 2.
Metoda CreateGraphics (), se regsete n toate clasele derivate din
263
Observaii
anterior.
Poligoane
Desenarea unui poligon se face foarte simplu, prin apelul metodei
DrawPolygon (). Metoda are ca parametri un obiect de tip Pen i un tablou de
puncte:
Graphics g = this.CreateGraphics();
Pen p = new P en (Color.Red, 3);
Point[] pt = { new Point(190, 90), new Point(140, 130),
new Point(150, 200), new Point(60, 100) };
// Deseneaz un poligon cu patru vrfuri
g .DrawPolygon(p, pt);
p.Dispose();
Aplicaia B ru s h e s E x a m p le
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 TextureBrush, care utilizeaz ca element de umplere o imagine.
Urmai paii:
1.
BrushesExample.
2. n fiierul Form1.cs, n clasa Form l, introducei la seciunea directivelor
using, secvena:
using System.Drawing.Drawing2D;
265
266
4.
La rulare, avem:
Observaii:
i
Desenarea textului
GDI+ furnizeaz cteva clase care se ocup cu desenarea textului. Clasa
Graphics are n acest scop mai multe metode Drawstring (). V vei acomoda
cu utilizarea acestora, urmrind exemplul de mai jos:
Aplicaia D ra w S trin g E x a m p le
Ca s desenai cu metodele Drawstring () trebuie s pregtii un font i o
pensul. Aplicaia testeaz dou dintre metodele Drawstring (). Prima scrie un
text la o locaie specificat de un punct, iar a doua scrie un text ncadrat ntr-un
dreptunghi.
267
Urmai paii:
1.
2.
3.
La rulare, obinei:
268
Dau un regat
pentru un cal
O
Observaii:
Clasa StringFomat are proprietatea Alignment, care permite s setai
alinierea textului n dreptunghiul specificat.
PointF i RectangleF sunt structuri similare Point i Rectangle, cu
diferena c admit coordonate reale.
A doua metod Drawstring () constrnge stringul s se ncadreze n
dreptunghiul specificat i l trunchiaz n aa fel nct cuvintele individuale
nu se frng.
De retinut:
s
s
s
269
Probleme propuse
1.
4.
5.
270
Capitolul 9
XML cu C#
XML (extensible Markup 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 post-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 XML
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.
<?xml version="l.0" encoding="utf-8" ?>
<biblioteca>
<carte nrvol ="12">
<titlu>Oameni si soareci</titlu>
<autor>John Steinbeck</autor>
</carte>
<carte nrvol ="7">
<titlu>Darul lui Humboldt</titlu>
<autor>Saul Bellow</autor>
</carte>
</biblioteca>
Capitolul 9. XML cu C#
271
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
Aplicaia X m lE x a m p le
Aplicaia citete date din fiierul Elevi, xml i le afieaz n mai multe
controale. ntr-un control de tip ListBox se afieaz numele elevilor, iar n alte trei
controale de tip TextBox, se afieaz coala, clasa i profilul clasei pentru elevul
care a fost selectat n list box.
Urmai paii:
1.
2.
3.
Vom edita fiierul XML. Mediul integrat include un editor de fiiere XML.
Acesta se invoc acionnd click drept n Solution Explorer pe titlul
proiectului, apoi Add, i New Item... n dialogul care apare, alegei din
panoul Template, iconul XML File. Completai cmpul Name cu Elevi.xml.
n editor scriei urmtorul document:
<?xml version="l.0" encoding="utf-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</profil>
</elev>
Capitolul 9. XML cu C#
273
<elev>
<nume>Nicoara Alina</nume>
<scoala>Gr. Sc. Industrial nr l</scoala>
<clasa>a Xl-a B</clasa>
<profil>telecomunicatii</profil>
</elev>
</absolventi>
Dup ce ai editat i ai salvat, copiai fiierul Elevi.xml din folderul
proiectului, n folderul /bin/Debug.
4.
5.
6.
"elev"
274
Elevi
A rdelean Eu
Costea Andrei
I Nicoara Alina
Informaii
Incarca XML______ ]
Ieire
Capitolul 9. XML cu C#
275
Important!
Aplicaia D o w n lo a d X m l
Aplicaia utilizeaz clasa WebClient din spaiul de nume System.Net
pentru a descrca un fiier de tip XML.
Urmai paii:
1.
2.
3.
4.
276
Observaie:
>
Pe numeroase site-uri i blog-uri vei gsi feed link-uri pentru subscriere, lat
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.
xml
Capitolul 9. XML cu C#
277
Aplicaia XmlTextReaderExample
Programul C# de mai jos folosete clasa XmITextReader 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
XmlTextReaderExample.
un
proiect
de
2.
tip
consol
cu
numele
using System;
using System.Xml;
class Program
{
XmITextReader reader =
new XmITextReader ("crti.xml");
// Citim pe rnd toate nodurile din document
while (reader.Read())
{
// n funcie de tipul nodului curent
switch (reader.NodeType)
{
// Dac nodul este un element
case XmlNodeType.Element:
Console.Write("<" + reader.Name);
Console.WriteLine(">");
break;
// Afim textul din fiecare element
case XmlNodeType.Text:
278
("
" +
reader.Value);
break;
// Afim "sfritul" elementului
case XmlNodeType.EndElement:
Console.Write(</" + reader.Name);
Console.WriteLine(">");
break;
}
}
} // Main()
}
4.
Mani
kbiblioteca>
Kcarte>
K T i t l u >
k/Pret>
Kftutor>
Ion Creanga
[</ftutor>
|</carte >
k/biblioteca>
111....
De retinut:
>
Metoda Read() a clasei XmlTextReader citete i returneaz
urmtorul nod din stream.
Proprietatea NodeType a clasei XmlNode 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 XmlTextReader obinei coninutul XML dintr-un fiier
sau dintr-un stream. n plus, are calitatea c v permite s analizai i s
prelucrai acest coninut.
Capitolul 9. XML cu C#
279
Crearea coninutului
XML cu XmITextWriter
t
Clasa XmITextWriter ofer o cale rapid cu care putei genera fiiere sau
sfream-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
XmITextWriter, 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 X m IT e x tW rite rE x a m p le
Vom crea un fiier cu coninut XML. Urmai paii:
1.
2.
280
Capitolul 9. XML cu C#
281
lib r r ie >
C c a rte ISBN ="186-383-S23">
< T itlu > A m in tiri d in c o p ila r ie < / T itlu >
<P r e t > 13.2 0</Pre t >
<Autor>Ion Creanga</Autor>
< /carte>
/ lib r r ie >
De retinut:
Probleme propuse
1.
2.
3.
4.
5.
282
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#.
C apitolul 10
Instrumente de lucru
Instrumentele software pe care le vom utiliza n lucrul cu bazele de date sunt:
283
Calitile 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:
Compacteaz informaia.
Bazele de date lucreaz cu cantiti uriae de date. Acestea se
memoreaz pe spaii relativ reduse.
ntreine
j datele.
Un SGDB ine evidena fiecrui fragment de informaie. Utilizatorii nu
trebuie s se preocupe acest aspect.
Previne inconsistenta
i datelor.
284
Capitolul 10.
285
In te g ra re a X M L .
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.
Arhitectura ADO.NET
ADO.NET are dou componente centrale:
1.
2.
1.
F u rn iz o rii d e d a te
286
.NET:
Spaiu! de nume
System.Data
System.Data.Odbc
System.Data.OleDb
System.Data.Sql
System.Data.OracleClient
System.Data.SqlClient
Descriere
Clase, interfee, delegri care definesc arhitectura
.NET. Aici sunt clasele care definesc dataset-urile
Data provider .NET pentru ODBC
Data provider .NET pentru OLE DB
Clase care suport funcionalitate specific SQL
Server
Data provider .NET pentru Oracle
Data provider .NET pentru SQL Server
Interfaa cu utilizatorul
ADO.NET
Data Set
Data
Table
Data Provider
Data Reader
Data Adapter
Command
Connection
XML
Baza de date
287
Pentru a nelege cum sunt definite n .NET aceste clase, vom lista numele acestor
clase pentru doi furnizori de date: Sql Server i OLE DB .NET. Reamintim c n
spaiul de nume System.Data.SqlClient sunt clasele furnizorului de date Sql
Server, iar n spaiul de nume System.Data.OleDb sunt cele ale furnizorului de
date, OLE DB.
Clasele specifice celor doi data provider-i sunt:
Furnizorul OLE DB .NET
OleDbConnection
OleDbCommand
OleDbDataReader
OleDbDataAdapter
Corespunde clasei
Connection
Command
DataReader
DataAdapter
System.Data.SqlClient.SqlDataReader
System.Data.OleDb.OleDbDataReader
System.Data.Odbc.OdbcDataReader
Oracle.OracleClient.OracleDataReader
2. Seturile de date
Dataset-ul este o component major a arhitecturii .NET. DataSet este
clasa care definete un dataset. Un dataset este o colecie de obiecte DataTable
care pot fi legate ntre ele cu obiecte de tip DataRelation. Dataset-urile preiau
de la data providers informaiile necesare din sursa de date sub forma unei copii
reduse a bazei de date. Prin urmare, un dataset poate include o baz de date
relaional cu tabele, relaii, vederi. Utilizatorul opereaz asupra tabelelor din
dataset, care sunt practic o copie a tabelelor reale din baza de date. Deoarece un
dataset este un obiect, cahe-ul pentru datele sale este n memorie.
Dafasef-urile implementeaz modelul de lucru deconectat de baza de date.
Cnd este necesar, dafasef-urile transmit bazei de date modificrile operate
asupra datelor.
Clasa DataSet, ca i celelalte clase care lucreaz cu un dataset se gsesc n
spaiul de nume System.Data. Tabelul urmtor descrie aceste clase:
288
DataSet
O b ie c te le s a le d e s c r iu s c h e m a n tre g ii b a z e d e d a te s a u a u n e i
s u b m u lim i a sa. C o n in e ta b e le i re la iile n tr e e le .
DataTable
O b ie c te le re p r e z in t o s in g u r ta b e l d in b a z a d e d a te . C o n in e
r n d u r i i c o lo a n e .
DataRow
DataColumn
DataView
DataRowView
DataRelation
R e p re z in t u n s in g u r r n d n tr-o ta b e l .
R e p r e z in t o c o lo a n n tr-o ta b e l .
DataTable
DataView.
O b ie c te le s o r te a z d a te le . N u s u n t in c lu s e n tr - u n
O b ie c te le r e p r e z in t u n s in g u r r n d n t r - u n
R e p r e z in t o re la ie n tre ta b e le . D e e x e m p lu , o re la ie d e
cheie
p r i m a r - c h e ie s tr in
Constraint
D e s c r ie o c o n s tr n g e r e n ta b e l , c u m a r fi u n ic i ta t e a v a lo r il o r n tr-o
c o lo a n c h e ie p rim a r .
2.
3.
Capitolul 10.
289
li
. j j Data Connections
ii* coala.mdf
*
Database Diagrams
.~i
_1 Views
.................._ _ _
Stored,
t:
Funcii
_S Synoni ;j?j
_ i Types
l_j Assemf
New Query
Refresh
Properties
290
6.
A X
d b o .T ab lel: T...E\SCO A LA .M D F )*
Column Name
Data Connections
Si
L J Tables
ffi
3 Views
ffi
~
Allow Nulls
int
[j]
Database Diagrams
u
| Column Properties
- l 3 Stored Procedures
D 3 Functions
A I
ffi~
: IC i Synonyms
r (--
..
f f i- C i Types
03 - C l Assemblies
No
'l
B
;
1,
..
.. . ..:
a i
Identity Specification
Yes
(Is Identity)
Yes
Identity Seed
y ;j
Data Type
IdElev
|
uu
8.
Data Type
IdElev
ij,. coala,mdf
Si
7.
Program.es
Delete Column
Relationships,,,
Allow Nulls
Capitolul 10.
Data Type
Allow Nulls
IdElev
int
Nume
nvarchar(30)
Prenume
nvarchar(30)
S3
Varsta
291
0
0
money
n c h a r(ld )
9.
Salvai proiectul i tabela apsnd butonul Save AII. n dialogul Choose Name
introducei numele tabelei: Elevi.
10. Pentru a nsera (design time) cteva rnduri cu date n tabel, expandai
nodul Tables n Database Explorer. Click dreapta pe tabela Elevi i
selectai Show Table Data.
Database
d
b
o
.E
lev
i:T
a
,..L
E
\5
C
0
A
L
A
.M
D
F
) sta
rtP
a
g
e
fi
'ii
C
o
lu
m
nN
a
m
e
Id
E
le
v
D
a
taC
o
n
n
ectio
n
s
3 Q
|.
co
a
la
,m
d
f
ffi 23D
a
ta
b
a
seD
ia
g
r
a
m
s
l_i T
a
b
les
fib
D
a
taT
y
p
e
|m
t
N
u
m
e
rw
a
rch
a
r(3
0
)
Prenume
n
v
a
tch
a
r(3
0
)
n
t
HUS ' A
d
dN
ew
T
a
b
le
1 1*:
A
d
dN
ew
T
r
ig
g
e
r
m iv
HR
N
ew
Q
u
e
ry
a v
O
p
enT
a
b
leD
efin
it
__f Views
:* ii S
to
redP
ij j* S
h
ew
T
a
b
leD
a
ta
SC r*51 Ft trwifWurM
11. S-a deschis Query Designer. Aici putei introduce manual date n tabel i
putei efectua interogri. Completai cteva rnduri, ca mai jos. Observai c pe
coloana idElev serverul nu v permite s introducei valori, deoarece este
coloan Identity i aceasta nseamn c SQ L S e rver ii atribuie valori n mod
automat:
Si
J-J
.....
f,
Elevi: Query(...LE\SCOALA.MDF)
ti------------1 IdElev
if|
1 .
2
0= t 3 d l 5
Nume
Prenume
Varsta
Pascu
lo a n
18
Nedelcu
Valentin
17
|3
Pop
Andrei
19
!4
Ilie
lo a n
18
[ MAL
MAL
MAL
MAL
292
12. Dac dorii s adugai i alte tabele bazei de date coala, de pild tabelele
Clase, Profesori, Materii, e foarte simplu: facei click dreapta pe Tables
n Database Explorer i alegei New Table., apoi repetai paii 6...11.
Nu vei face build 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 retinut:
9
O cheie primar (primary 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 coloan identitate (Identity column) 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.
varchar (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.
2.
Capitolul 10.
293
Butoanele
panourilor
w) s i
iU ? 0
i m 6=
Query4: Query...E\SCOALA.MDF)
Iii
s ta r t P age
X
A-
Diagram Pane
IdElev
jV iN u m e
li v ] P re n u m e
jivj V a rs ta
v
>
<
C olum n
:<
.... ^
SELECT
Alias
Table
O u tp u t
N um e
Elevi
P re n u m e
Elevi
V a rs ta
Elevi
j
v
Criteria Pane
4l
>
SQL Pane
N um e, P re n u m e j V a rs ta
E levi
FROM
|
Show Result
Pane
Num e
P re n u m e
V a rs ta
P ascu
lo a n
18
N e d e lc u
V a le n tin
17
P op
A n d re i
19
Ilie
lo a n
18
294
Comanda SELECT
SELECT este utilizat pentru selecatrea datelor dintr-o tabel. Rezultatul
este returnat ntr-o form tabelar, numit result set.
Sintax:
SELECT nume_coloane FROM tabela
Exemplu:
Introducei n SQL Pane comanda urmtoare, dup care o executai cu un
click pe butonul Execute SQL:
SELECT 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 s e l e c t , 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:
1
-
ii '
Nume
Prenume
Ilie
loan
Nedelcu
Valentin
Pascu
loan
' i Pop
Andrei
Clauza WHERE
where
Exemplu:
Introducei n SQL Pane comanda:
SELECT * FROM Elevi
WHERE Varsta > = 1 8
Capitolul 10.
295
Rezultat:
IdElev
Nume
Prenume
Varsta
Pascu
loan
18
Pop
Andrei
19
Ilie
loan
18
Sintax:
INSERT INTO nume_tabel
VALUES valoarel, valoare2, ...
...)
Exemplu:
Introducei n SQL Pane:
INSERT INTO Elevi (Nume, Prenume, Varsta)
VALUES ('Florea', 'Constantin', 99)
Rezultat:
Pentru a vedea rezultatul, avem nevoie de un result set ntors de o
instruciune s e l e c t .Introducei interogarea:
SELECT * FROM Elevi
IdElev
Nume
Prenume
Varsta
11
[2
Pascu
loan
18
Nedelcu
Valentin
17
13
Pop
Andrei
19
<
......i I4
Ilie
loan
18
;7
Florea
Constantin
99
Comanda UPDATE
Comanda este utilizat pentru modificarea datelor ntr-o tabel.
296
S in ta x :
UPDATE nume_tabel
SET coloanl = valoarel, coloan2 = valoare2, ...
WHERE coloan = valoare
N um e
P renum e
V a rsta
Pascu
lo a n
104
N ede lcu
V alentin
17
Pop
A n drei
19
Ilie
lo a n
104
F lo re a
C o n s ta n tin
99
*}
Capitolul 10.
297
l.
N um e
P ren um e
V a rs ta
N e d e lcu
V a le n tin
1?
Pop
A n d re i
19
Sintax:
CREATE TABLE nume_tabel
(
coloanal tip_dat,
coloana2 tip_dat,
)
Exemplu:
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),
NrElevi int)
Rezultat:
n Database Explorer a aprut tabela Clase. Acionai click drept asupra
numelui clasei i selectai Open Table Definition:
C o lu m n N a m e
ID C la s a
D a ta T y p e
1 v a rc h a r(5 )
A llo w Nulls
i
P ro fil
v a r c h a r( 2 0 )
N rE le vi
in t
Sintax:
ALTER TABLE tabel
ADD coloan tip
ALTER TABLE tabel
DROP COLUMN coloan
298
Exemplu:
Introducei n SQL Pane comanda urmtoare, dup care o executai cu un
click pe butonul Execute SQL:
A L T E R TABLE Clase
ADD D i r i ginte varchar(20)
Rezultat:
n Database Explorer acionai click drept asupra numelui clasei i selectai
Open Table Definition:
Column Name
D ata Type
Allow Nulls
IDCIasa
v a rc h a r(5 )
Profil
v a rc h a r(2 0 )
NrElevi
int
| D iriginte
| v a rc h a r(2 0 )
Exemplu:
Introducei n SQL Pane comanda pentru tergerea coloanei Diriginte:
A L T E R TABLE Clase
DROP C OLUMN Diriginte
Rezultat:
C olum n N am e
D a ta T y p e
ID C Ia sa
v a r c h a r(5 )
P ro fil
v a rc h a r(2 0 )
N rE levi
in t
A llo w Nulls
Sintax:
DR OP TABLE
ta b e l
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:
Capitolul 10.
299
Controlul DataGridView
Acest control este vedeta controalelor pentru afiarea datelor. Clasa
DataGridView permite construirea unei tabele adaptabile. Celulele, rndurile,
coloanele se seteaz prin intermediul proprietilor Rows i Columns.
D ata T yp e
j int
Allow Nulls
Nume
n va reha r(1 5)
Prenum e
n va rc h a r(1 5 )
D ata N a sterii
d a tetim e
S p o rtu lP ra ctica t
n va rc h a r(3 0 )
Table Data.
4.
300
A 1I
L
'5=1
d ll
C ursor
D efault
DataM em ber
1
(n one)
D e fa u 1 : M
Dock
Q - Q J O th er D ata Sources
EditMc
Enable
J j]
S3
Enable
Gener
F o rm l List Instances
GridCc
La rulare obinei:
IdSportiv
1
2
..........
,j 3
....
Nume
Prenume
DataNasterii
SportulPracticat A
Dita Tomescu
Constantina
23.01.1970
Atletism
Izbasa
Sandra
28.05.1998
Gimnastica
Alina
30.08.1982
Judo
| Dumitru
Andrunache
1Georgeta
14.04.1976
Canotaj
r5
Susanu
1Viorica
29.10.1975
Canotaj
7>
L
Exist i alte variante vizuale pentru popularea controlului.
Varianta a 2-a
Procedai dup cum urmeaz:
Paii 1, 2, 3, 4 sunt identici cu cei specificai anterior. Continuai astfel:5
A dd N ew D a ta S o urce..,
E dit D a ta S e t w ith D esigner
F j
Capitolul 10.
301
Sfi/fgNH
0-
Tables
+ 0 Z3 S portivi
i
;
Views
-Q t#
S tore d P rocedures
9 X
SportDataSet.w d
^Start Page
FormUS F o rm l.e s [D e s ig n ]*
Sportivi; Que
,;J L'J |
' r, SpctDat-aSet
S i- i Sportivi v
bl IdSportiv
bi Nume
,'.T~
bi Prenume
DataNauterii
abi SportijPracticai
8.
Facei Build i rulai cu F5. Vei obine popularea controlului cu datele din
tabel.
Varianta a 3-a
Procedai astfel:
Paii 1,2, 3, 4 sunt identici cu cei ai aplicaiei anterioare. Continuai astfel:
5.
situ U
SportData m
Add New Data Source. ..
Edit DataSet with Designer
302
J
j B
-* 9 X
Sport.DataSet.xsd*
Start Page
Forml.cs*
p Data Corrections
Sportivi
Ufc Spwtrodf
H8 0 1 Database Diagrams
S3 t i l Tables
0 3 Sportivi
33 IdSportiv
13 Nume
j O Prenume
3 ] DataNasterii
23 SportulPracticat
IdSportiv
Mume
Prenume
DataNasterii
SportulPracticat
..r ^ 7 ..;
IP >
% F i,6et0ata()
C3 Views
Observaii:
>
>
Toate cele trei variante de populare a controlului D ataG rid V iew realizeaz o
legare 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.
Capitolul 10.
IDSportiv
Prenume
Data Naterii
303
DataGridView Tasks
fiabil Nume
<
0r
j [abi; Prenume
i {abi; Data Naterii
j ;abl Sport Practicat
if'!41 _
Enable Editing
Enable Deleting
MaxInputLength
32767
Readonly
False
Resizable
True
SortMode
Automatic
Ajj
B Data
DataPropertyName
(none)
B Design
(Name)
ColumnType
~ ..... .... "
[
Add...
........ ..j[
Remove
Enable Adding
Column 1
DataGridViewTextBoxColu:v j
(Name)
Indicates the name used in code to identify the
object.
Cancel
304
C a p ito lu l 11
Nume
Prenume
V ersta
Nedelcu
Valentin
17
Pop
Andrei
19
Executm dou operaii asupra tabelei Elev: inserarea unui rnd nou i selectarea
rndurilor.
Urmai paii:
1.
2.
Capitolul 11.
305
namespace ConsoleApplicationl
{
class SQLDataProvider
{
static void Main(string[] args)
{
// Construim stringul de conectare
(connection string)
string connString =
0"server = .\sqlexpress;
Database=Scoala.mdf;
trusted_connection=True;
AttachDbFileName =
C:\DatabaseExample\DatabaseExample\bin\Debug\Scoala.mdf";
/ /
// Pregtim interogrile
string sqll = 0"SELECT * FROM Elevi";
string sql2 = 0"INSERT INTO Elevi
(Nume, Prenume, Varsta)
VALUES
('Axente', 'Mihai', 20)";
// Deschidem conexiunea
conn = new SqlConnection(connString);
conn.Open();
// nchidem reader-ul
// pentru a putea fi refolosit
reader.Close();
// un r e s u l t s e t
cmd = new SqlCommand(sqll, conn);
306
reader = crad.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], reader["Prenume"] ,
reader[3]);
Console.WriteLine();
}
catch (Exception e)
{
Console.WriteLine("Eroare: " + e ) ;
}
finally
{
// Conexiunea se nchide indiferent dac se
// arunc sau nu excepii
reader.Close();
conn.Close();
conn.Dispose();
}
} //Main()
}
}
3.
. . . _
hi
Capitolul 11.
307
>
Executarea interogrii
>
>
>
>
>
308
{
conn.Open();
SqlCommand cmd = new SqlCommand(sqll, conn) ;
reader = cmd.ExecuteReader();
// cod ...
while (reader.Read())
Console.WriteLine("{0}
{1} {2}",
reader[1], reader["Prenume"],
reader[3]) ;
reader.Close();
}
Observai c nu mai este nevoie nici mcar s nchidei conexiunea,
deoarece de acest lucru se ocup acum C#.
Capitolul 11.
309
E x e c u t in te ro g ri s a u p ro c e d u r i s to c a te
R e p r e z in t o c o n e x iu n e la o s u r s d e d a te
P e rm ite c itir e a n u m a i n a in te , a u n u i s tre a m d e r n d u ri
d in tr-o s u r s d e d a te
OleDbDataAdaptor
R e p re z in t
le g tu r
n tre
su rsa
de
d a te
i d a ta s e t,
f o lo s it p e n tr u o b in e re a i s a lv a r e a d a te lo r.
Este uor de remarcat similitudinea ntre clasele furnizorului OLE DB i cele ale
SQL Server 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 Persoane.mdb, cu
urmtoarea schem:
310
} f^ ie r
Ic te re
Vtzuateare
Interare
Instrumente
li Persoane: Tabel
I4un*e cmp
S* ID
Nume
Prenume
Dafc^testar*
Tip de date
AutoNumerdtare
Text
Text
Dat/Ora
3.
5.
{
// Setm numrul coloanelor i textul
dataGridViewl.ColumnCount = 4;
dataGridViewl.Columns[0].HeaderText =
dataGridViewl.Columns[1].HeaderText =
dataGridViewl.Columns[2].HeaderText =
dataGridViewl.Columns[3].HeaderText =
h e a d e r - e lor
"ID-ul";
"Numele";
"Prenumele";
"Data Naterii";
// Stringul de conectare
string connString =
0"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 read e r
OleDbConnection conn = null;
OleDbDataReader reader = null;
// Crem conexiunea
using (conn = new OleDbConnection(connString))
Capitolul 11.
311
// Deschidem conexiunea
// Se execut interogarea
OleDbCommand cmd = new OleDbCommand(sql, conn);
reader = cmd.ExecuteReader();
{
r = new string[4]{ reader[0].ToString(),
reader[l] .ToStringO ,
reader [2] .ToStringO ,
reader [3] .ToStringO };
}
reader.Close();
> // using
}
6.
ID-ul
Numele
Prenumele
Data Naterii
Voicu
Ionel
16.01.1988 00:0...
Grapini
Grigore
10.11.1987 00:0...
Pop
loan
21.02.1990 00:0...
U liniei
Sorin
114.07.1991 00:0...
y& em
&mhhs
ivi. N
De retinut:
>
>
312
>
Rndurile
se
adaug
n
control
cu
metoda
Add():
dataGridViewl.Rows.Add(r) ; , unde r este un ir de stringuri care
reine valorile reac/er-ului.
Declaraia using 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 reader-ul.
Remarcm similitudinea codului i a tipurilor utilizate pentru provider-ii
SQLServer i OLE DB.
>
>
Aplicaia O d b c E x ce lE xa m p le
Vom reliza o aplicaie de tip Windows Forms care se conecteaz prin
providerul ODBC la un fiier Excel 2003, n care pe prima foaie este un tabel.
Datele se citesc din sursa de date i se afieaz ntr-un control DataGridView.
Urmai indicaiile:
1.
A
J. . . B _ | _ ..... C .
Id P ro d u s
D e n u m ire P re
C a n tita te
1 P a in e
2 L a p te
23
3 Ia u rt
45
4 C o la
21
200
Capitolul 11.
313
3.
=
=
=
=
"ID-ul";
"Nume";
"Pre";
"Nr Produse";
// Stringul de conectare
string connString =
@"Driver={Microsoft Excel Driver (*.xls)};
Driverld=790;
Dbq=C:\teste\Produse.xls;
DefaultDir=C:\OdbcExcelExample\OdbcExcelExample\bin\Debug";
// Stringul de interogare
// [Foaiel$] poate fi [sheetl$] dup caz
string sql = @"select * from [Foaiel$]";
// Crem conexiunea
using (conn = new OdbcConnection(connString))
{
conn.Open();
// Deschidem conexiunea
// Se execut interogarea
OdbcCommand cmd = new OdbcCommand(sql, conn);
reader = cmd.ExecuteReader();
314
{
r = new string[4]{ reader[0].ToString(),
reader[1].ToString(),
reader[2].ToString(),
reader[3].ToString() };
dataGridViewl.Rows.Add(r);
}
reader.Close();
} // using
}
6.
La rulare obinei:
ID-ul
Nume
Pre
Nr Produse
Paine
200
Lapte
23
Iaurt
Cola
....f l H
,,
45
21
v
Observaii:
j
>
>
Aplicaia O d b cM yS Q L
Scopul acestei aplicaii este acela de a arta modul n care v putei conecta
la o baz de date MySQL 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:
Capitolul 11.
>
>
315
------------------------- +
Database
+------------
316
6.
7.
8.
Capitolul 11.
317
ser DSN ; System DSN j File DSN | Drivers | Tracing ; Connection Pooling ] About
User Data Sources:
Add...
)V
4
4
4
4
6
6
Finish
3.
jnnect to
to you.
2
2v
'
Cancel
318
C)
Crearea aplicaiei C#
2.
4.
{
dataGridViewl.ColumnCount = 3;
dataGridViewl.Columns[0].HeaderText = "Numele";
dataGridViewl.Columns[1].HeaderText = "Prenumele";
dataGridViewl.Columns[2].HeaderText = "Varsta";
string connString =
"dsn=ConexiuneMySQL;User=root;Password=iuliuta";
string sql = @"select * from elevi";
OdbcConnection conn = null;
OdbcDataReader reader = null;
using (conn = new OdbcConnection(connString))
{
conn.Open();
// Se execut interogarea
OdbcCommand cmd = new OdbcCommand(sql, conn);
using (reader = cmd.ExecuteReader())
{
string[] r = null;
while (reader.Read())
Capitolul 11.
319
r = new s t r i n g [ 3 ] { r e a d e r [0] .T o S tr in g O ,
reader [1] .ToStringO ,
reader [2] .ToStringO };
dataGridViewl.Rows.Add(r);
}
5.
N um ele
Blaga
V ersta
Prenum ele
|
Ionel
\ 25
H orga
Lu cia n
25
Chifa
Ionel
19
j
Precizri:
320
C a p ito lu l 12
instan
clasei
DataSet,
utilizai
unul
dintre
321
// Creeaz dataset-ul
DataSet ds = new DataSet ();
// ncarc dataset- ul cu tabela elevi. 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 Fill a
adaptorului umple d a ta s e t -ul cu tabela elevi.
Exist nc dou versiuni ale constructoului clasei SqlDataAdaptor. Primul nu are
parametri, iar al doilea primete un obiect de tip SqlCommand:
SqlDataAdapter da = new SqlDataAdapter();
SqlDataAdapter da = new SqlDataAdapter(cmd);
Pentru a ncrca n d a ta s e t toate tabelele din baza de date, utilizai alt versiune a
metodei Fill:
d a .Fill(ds);
dt
d s .T a b l e s [" p r o d u s e " ];
322
{
// Pentru fiecare coloan
foreach (DataColumn col in dt.Columns)
Console.Write(row[col]); // Accesare indexat a
// valorii unei celule
Console.WriteLine();
}
323
Aplicaia U p d a te D a ta b a s e
Aplicaia de tip Windows Forms acceseaz o baz de date S Q L S e r v e r
2 0 0 5 i afieaz ntr-un control DataGridView datele dintr-o tabel. La apsarea
unui buton, modificrile operate de utilizator n celulele gridului se propag n baza
de date.
1.
UpdateDatabase.
2.
3.
4.
5.
Data Type
Allow Nulls
int
Titlu
nvarchar(50)
Autor
nvarchar(20)
Pre
int
324
Data Source;;
, S'
LibrarieDataSet
a S3 cwti
ai Cod
lattfi Titlu
iafel Autor
Start Page
'j
(fi
dbo.Carth Ta.,.\UERAP
m Carti
'9 cot)
iu
Autor
Pre
i|SjPre
...
F*,GetOata ()
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.
{
//
//
//
ta
// Crem un dataset
libDataSet = new LibrarieDataSet();
// Umplem dataset-ul cu datele din tabela Carti
t a .Fill(libDataSet.Carti);
// bs permite legarea controlului dataGridViewl
// la sursa de date din dataset
BindingSource bs = new BindingSource(libDataSet,
" C a r ti" ) ;
325
}
8.
{
// Propagm modificrile spre baza de date.
int afectate = ta.Update(libDataSet.Crti);
labell.Text = afectate + " rnduri afectate";
}
9.
0 r n d u ri a fe c ta te
Cod
Salveaza
Titlu
Autor
ion
Liviu Rebreanu
1437
Rou si Negru
Stendhal
33
3512
Quo Vadis
Sienkiewicz
35
6423
:Ana KArenina
Pre
: 32
48
Tolstoi
<
Dac spre exemplu operm modificri n celulele din rndurile 3 i 4, iar apoi
apsam S a lv e a z a , obinem:
2 r n d u ri a fe c ta te
*
<
Cod
Titlu
Autor
Pre
231
Ion
Liviu Rebreanu
32
1437
Rou si Negru
Stendhal
33
3512
Quo Vadis
Henrik Sienkiewicz
35
6423
Ana Karenina
48
/V
.....
>
326
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 Build 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 Build 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 Build i baza de date original se copiaz peste cea din
\Bin\Debug.
Dataset-urile i XML
Cnd lucrai cu cfafasef-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 WriteXml () a clasei DataSet astfel:
ds.WriteXml(@"C:\date.xml") ;
Cnd deschidei o nou sesiune a aplicaiei, avei alternativa de a rencrca n
d a ta s e t datele preluate din fiierul XML. Citirea se face cu metoda ReadXml ():
d s . R e a d X M L (" C :\ d a t e .x m l " );
Exemplu:
Ne ntoarcem la aplicaia U p d a te D a ta b a s e , realizat anterior. Introducei ca
ultim linie n corpul metodei de tratare a evenimentului Click pentru butonul
S a lv e a za , apelul:
libDataSet.WriteXml(@"C:\carti_bune.xml");
Rulai cu F5, apoi cutai fiierul carti_bune.xml.
informaiile din d a ta s e t s-au salvat n format XML.
IU
binding):
* Legarea simpl.
Legarea complex.
Aplicaia S im p le D a ta B in d in g
1.
2.
3.
{
InitializeComponent();
// Legm proprietatea Text a butonului (primul
// parametru) de proprietatea Text a text box-ului
buttonl.DataBindings.Add("Text", textBoxl, "Text");
}
4.
{
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
U n u doi tre
U n u doi trej
Click pe buton
Aplicaia C o m p le x D a ta B in d in g l
Aplicaia utilizeaz utilizeaz facilitile mediului integrat pentru a lega
proprietatile unui control DataGridView la o tabel a unei baze de date SQL
Server 2005 Express. Urmai paii:
1.
ComplexDataBinding 1.
2.
3.
Data Type
j IDConcert
329
Allow Nulls
| int
TipConcert
nvarchar(20)
SustinutDe
nvarchar(50)
Data
datetirne
Locaie
nvarchar(20)
5.
Specta
i 43.
B a l Spectacoie-DataSet
Si-(jpl
~1
!J
DataGridView
ComboBox
j 1*2 listBox
i EU
6.
Details
dbo.Concerte:.. .ECTACOIE.MDF)
SpectacoleOataSet.xsd
i V.-11 |
SpectacoleD-ataSet .
* j - i Concerte v
s?l spectacoleDataSet
' ) tabteAdapterManager
concerteBindingSource
* } - concerteKndlngNavigatar
t i ConcerteTableAdapter
330
7.
Rulai cu F5.
Vei obine:
1IDConcert
TipConcert
1 Rock
-2
Hip Hop
House
Country
Aid
SustinutDe
Data
: Metallica
12.03.2003
; Eminem
04.07.2009
Mickey Oliver
j Martina McBride
~~T ~ .... ' ........~
15.11.2009
24.02.2003
V.
< '...
ncercai singuri:
n proiectul anterior, tergei din d e s ig n e r tra y apsnd tasta d e le te toate
referinele. tergei i gridul de pe form. n fereastra Data Sources, selectai
D e ta ils , apoi tragei cu mouse-ul tabela pe suprafaa formei. Pe suprafaa formei
vor aprea patru controale de tip TextBox i un DateTimePicker. Fiecare control
este legat la una dintre coloanele tabelei.
Toate controalele indic acelai rnd din tabel. Navigarea de la un rnd la altul se
face cu ajutorul butoanelor sgeat din controlul ToolStrip din partea de sus a
formei.
A p lic a ia C o m p le x D a ta B in d in g 2
Modificm proiectul anterior astfel nct s legm proprieti ale controalelor
331
IDConcert
TipConcert
SustinutDe
Data
Locaie
C on certeT ab leA dapter
FilljGetData () j
Add Query..,
I
Configure,.,
7.
332
Toolbox
Start Page
dbo.Concerten,.ECTACOLE.MDF)
Spe
- ComplexDataSindingl Components
; ^
Pointer
| 10 SpectacoleDataSet
! ( 0 ConcerteTabteAdapter
\ < 0 TabteAdapterManager
*
C o m m o n C on trols
C o n ta in e rs
r
M e n u s & T o o lb ars
- Data
! ^
0 RNDURI AFECATATE
Pointer
Salveaza
j |g^| DataSet
D ...................................................
;:p i DataGridVew
J-
i ? BmdmgSource
8.
tandingSour ce 1
(Name)
b in d in g S o u rc e l
! 'ii
AIlowNew
True
;EI (AppiicationSettings)
DataMember
(Name)
(none)
. - tv
b is h
; '3
b in d in g S o u rc e l
AllowNew
True
DataMember
I C o n c e rte
v,> None
9.
Concerte
SpectacoleD ataSet
b in d in g S o u rc e l
1S u s tin u tD e
0 R A N D U R I A F E D A T A ' V alue M e m b e r
5 e |e c te d V alue
_1
(n o n e )
333
10. Selectai controlul TextBox cel mai de sus. n fereastra P ro p e rtie s , expandai
itemul Data Bindings i setai proprietatea Text la valoarea SustinutDe :
iQ (DataBindings)
(Advanced)
' ^
Tag
(none)
Text
(none)
bindingSourcel
jj
IDConcert
TipConcert
jO SustinutDe
11. Executai aceleai operaii de la pasul 10, pentru urmtoarele trei texffaox-uri,
cu diferena c vei lega proprietatea Text la celelalte coloane ale tabelei.
12. La ncrcarea formei, vom umple d a ta se t-u \. Dublu click pe suprafaa formei,
n E d ito ru l de C o d scriei:
private void Forml_Load(object sender, EventArgs e)
{
// Fill () ncarc datele din baza de date n dataset
concerteTableAdapterl.Fill(spectacoleDataSet.Concerte);
{
// Aplicm sursei de date modificrile fcute
bindingSourcel.EndEdit() ;
// Updatm baza de date
int afectate =
concerteTableAdapterl.Update(spectacoleDataSet);
labell.Text = afectate + " rnduri afectate";
}
14. Rulai cu F5.
Se obine:
334
Forml
M e ta llic a
Eminem
M ic k e y O livet
M a rtin a M c B rid e
Erninem
H ip H o p
: B u c u re ti
04.07.2009
1 r nduri a fe c ta te
S a lv e a z a
335
Capitolul 13
Aplicaia Scoaia
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 in t e g r ita te a d a te lo r. Vom seta regula de tergere pentru
aceast relaie: N CASCAD.
Atentie !
V sugerm s nu ocolii acest proiect, deoarece pe structura lui vom lucra
n temele urmtoare, unde va fi dezvoltat i completat.
1.
2.
Column Name
j C lasa
D a ta T y p e
n v a rc h a r(5 0 )
N rE levi
in t
D irig in te
n v a rc h a r(B O )
Allow Nulls
336
Tabela Elevi
C o lu m n N am e
I ;
D a ta T y p e
Id E le v
in t
N um e
n v a rc h a r (5 0 )
M e d ia
re a l
A llo w N ulls
jiJ
Clase
S tart Page
15
Clasa
IdElev
NrElevi
Nume
Diriginte
Media
Clasa
5.
Relationship name:
m
Elevi
Clasa
stabilii regulile relaiei de cheie strin. Setai pentru Delete i Update regula
C a s c a d e , apoi apsai OK:
INSERT Arid UPDATE Specification
Update Rule
Cascade
Cascade
B Id e n tity
(Name)
Description
FK Elevi Clase
337
7.
8.
9.
elev.
Adugai meniului Rapoarte, opiunile: Diriginti-clase i Media pe clase.
10. Configurm dataset-ul aplicaiei cu ajutorul Wizard-ului. n fereastra D a ta
S o u r c e s , 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 D a ta S o u rc e s , 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 o t: ^e:
338
Add Q ue ry.,,
Configure..,
2.
339
7
W hat type of SQL query would you like to use?
Returns a single value (for example, Sum, Count, or any other aggregate function).
O UPDATE
Changes existing data in a table.
O DELETE
Removes rows from a table.
INSERT
4.
BB8i i
ZHuBinAT
mm
Type your SQL statement or use the Query Builder to construct it. What data should be loaded into the
table?
W hat d ata should the ta b le load?
i INSERT IN' : - ,: ; Oase' ([dasa], [NrElevi], [Diriginte]) VALUES (@Clasa, @NrElevi, Diriginte);
: SELECT diasa, Mflfewi, Diriginte FROM Clase WHERE (Clasa = Clasa)
( Query Builder... j
5.
340
>
* (All Columns)
1+ Clasa
E i NrElevi
i+ j Diriginte
V
>
<
Column
New Value
Clasa
Clasa
NrElevi
NrElevi
~
ft
v
-r
i __ __j "
Execute Query
:.
OK
Cancel
7.
este
341
vizibil
adaptorul
{
if (textBoxl.Text == "" || textBox2.Text == "" ||
textBox3.Text == "")
{
MessageBox.Show(
"Nu ati completat toate cmpurile!");
return;
}
claseTableAdapter1.Insert(textBoxl.Text,
int.Parse(textBox2.Text), textBox3.Text);
Close () ;
}
9.
{
// Instaniem forma FormlnsertClasa
FormlnsertClasa fInsCl = new FormlnsertClasa();
fInsCl.ShowDialog();
// Acum n baza de date avem un rnd nou
// ncrcm datele din baza de date n dataset
claseTableAdapter.Fill(scoalaDataSet.Clase);
}
10.
Clase
Elevi
Rapoarte
NrElevi
IdElev
Diriginte
Popescu
Nume
ForrnlnsertC,
Vernescu
Colcei
Nr Elevi:
Diriginte: iDanciu Elena
342
O UPDATE
343
G e n e ra te th e s to r e d p ro c e d u re
The SELECT statement will be used to create a stored procedure that will be called by
the query.
f ? - :A
Type your SQL statement or use the Query Builder to construct it. What data should be loaded into the table?
start Page
Forml.es
Forml.cs [Df
J
AS
{
if (textBoxl.Text == "" || textBox2.Text == "" ||
textBox3.Text == "")
{
MessageBox.Show(
"Nu ati completat toate cmpurile!");
return;
344
i n t i n t r e g = O;
i f ( ! i n t . T ry P a rs e (te x tB o x 2 . T e x t,
o u t in tr e g ) )
{
M essa ge B o x. Show (
"N r e le v i tr e b u ie
re tu rn ;
s f i e
num r i n t r e g ! " ) ;
}
i f (
( in t ) c la s e T a b le A d a p t e r l. M a iE x is t a C la s a (
te x tB o x l.T e x t )
= = 1)
{
M e s s a g e B o x . S h o w ( " C la s a e x i s t a
re tu rn ;
d e ja !" ) ;
}
c la s e T a b le A d a p te r l. I n s e r t ( t e x t B o x l. T e x t,
i n t . P a rs e (te x tB o x 2 . T e x t ) , te x tB o x 3 . T e x t ) ;
C lo s e ( ) ;
IM PO R TA N T!
M e to d a insert, ca d e a ltfe l to a te m e to d e le c a re c o n in in te ro g ri, p o t s
a ru n c e e xce p ii. D e a ce e a , tre b u ie in c lu s e n b lo c u ri
N o i n u a m f c u t-o aici, p e n tru cla rita te .
try-catch.
Tem de lucru:
Im plem entai facilitatea de adugare a unui nou e lev n baza de date la
selectarea opiunii A d u g e le v din meniul Elevi. Trebuie s creeai o funcie
suplim entar care interogheaz baza de date determ innd dac valoarea pe care
o introduce utilizatorul pentru cm pul C la s a exist sau nu n tabela C la s e .
WB
terge
Capitolul 13.
2.
345
(
FormDeleteClasa fDelCl = new FormDeleteClasa();
fDelCl.ShowDialog();
// Rencrcm cele dou tabele din dataset
// cu datele modificate din baza de date
ClaseTableAdapter.Fill(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)
{
claseTableAdapterl.DeleteClasa(textBoxl.Text);
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
Tem de lucru:
Implementai facilitatea de tergere a unui elev, la selectarea opiunii terge
2.
3.
4. n dialogul Add Table, selectai tabela Clase, apsai Add, apoi click pe
butonul Close.
5.
347
* (All Columns)
j v . Clasa
NrElevi
v Diriginte
< *4
Table
Output
Diriginte
Clase
Clasa
Clase
Column
Alias
<
0
,v
SELECT
FROM
Sort Type
pf
Diriginte., Clasa
dbo. Clase
6.
7.
Database Explorer
dbo.View2i Vi,..A\SCOALA,MDF)*
|J Data Connections
Jjr, coala.mdf
SI- J j i Database Diagram^
& C l Tables
dti- JJJ Clase
$i
13 Elevi
B- C J Views
S ' g l i ViewDirigClase I
[3
Diriginte
JO Clasa
-
Stored Procedures
S' C j
Functions
51 L_i Synonyms
$ Types
JJJ Assemblies
8.
9.
Acionai dublu click pe opiunea D irig in ti-c la s e din meniul R a p o a rte , aflat pe
F o r m l. n corpul metodei de tratare scriei:
348
4.
5.
.......................
.... .
<
j * (A ll C o lu m n s)
U * (AN C o lu m n s )
0
C la s a
349
[* =
= 4
-1
[jK fia v
|__ |N um e
N rE levi
P I D irig in te
[< -
L i M e d ia
[ j C lasa
:<
T a ble
O u tp u t
C lasa
C lase
G ro u p By
D irig in te
C lase
G ro u p By
E levi
C olum n
SELECT
FROM
M edia
Alias
M e diaC lasei
S , ,.
S , ,,
G ro u p By
F ilte r
| A vg
d b o ,C la s e ,C la s a , d b o .C la s e .D irig in te j A V G (d b o ,E le v i.M e d ia ) AS M e d ia C la se i
d b o , C lase IN N E R JO IN
d b o ,E le v i ON d b o ,C la s e ,C la s a = d b o ,E le v i,C la s a
GROUP BY d b o .C la s e .C la s a , d b o ,C la s e .D irig in te
avg
().
6.
7.
}
8.
Rulai cu F5.
350
Probleme propuse
1. Adugai aplicaiei coala un View 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 F irm 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.
4.
Bibliografie
[1]
[2]
[3]
Jesse Liberty.
Andrew Troelsen .
Apress 2008.
[4]
[5]
Trey Nash.
[6]
Stanley Lippman. C#
A c c e le ra te d C # 2 00 8. Apress 2008
P rim e r: A P ra c tic a l A p p ro a c h . Pearson Education
Inc. 2003
[7]
Herbert Schildt. C# 2 .0
[8]
Donis Marshall.
P ro g ra m m in g M ic ro s o ft V is u a l C# 2 0 0 5 : T he L a n g u a g e .
[9]
Rob Harrop.
[10]
[11]
Paul Kimmel.
[12]
[13]
[14]
Matthew MacDonald.
P ro
.N E T
2 .0
W in d o w s
F o rm s
and
C u s to m
[15]
[16]
Daniel Solis.
[17]
[18]
[19]
MAHESH CHAND.
A P ro g ra m m e rs G u id e to A D O .N E T in C#. Apress
2003.
[20]
Mickey Williams.