You are on page 1of 219

Uvod u C#

Ovo je prva lekcija programiranja u jeziku C#. Prvi deo vas uvodi u osnovna znanja koja su
neophodna da bi ste se kasnije lako snali. Ovde emo napraviti kratak pregled jezika C# i
.NET okruenja, opis ovih tehnologija, prednosti njihove upotrebe, kao i meusobnu
povezanost.
Poeemo sa osnovnim pitanjima vezanim za .NET okruenje. Ovo je nova tehnologija
koja sadri nove koncepte, sa kojima je isprva teko uhvatiti se u kotac, uglavnom zbog
toga to predstavlja potpuno nov nain rada u razvoju aplikacija. Kratak pregled osnova
od velike je vanosti za razumevanje programiranja u jeziku C#.
Nakon kratkog pregleda prei emo na prost opis samog jezika C#, ukljuujui korene i
slinost sa jezikom C++.

ta je .NET okruenje?
.NET okruenje je nova i revolucionarna platforma za razvoj aplikacija napravljena od
strane Microsofta.
Primetiete da nismo rekli razvoj aplikacija u operativnom sistemu Windows". lako prva
verzija .NET okruenja radi na operativnom sistemu Windows, budui planovi
podrazumevaju i rad na drugim sistemima, kao to su FreeBSD, Linux, Macintosh, pa ak i
na ureajima klase linog digitalnog asistenta (PDA). Jedan od kljunih razloga za razvoj
ove tehnologije je namera da ona postane sredstvo kojim se vri integracija razliitih
operativnih sistema.
Pored toga, ova definicija .NET okruenja ne ograniava mogunosti bilo kog tipa
aplikacije. Ogranienja zapravo ne postoje - .NET okruenje daje vam mogunost izrade
Windows aplikacija, Web aplikacija, Web servisa i skoro svega ostalog to bi ste mogli
zamisliti.
.NET okruenje dizajnirano je tako da se moe koristiti iz bilo kog jezika: C#, C++, Visual Basic,
JScript, pa ak i starije jezike kao to je COBOL. Da bi sve to funkcionisalo, pojavile su se i
posebne verzije ovih jezika za .NET: Managed C++, Visual Basic .NET, JScript .NET, kao i razni drugi.
Ne samo da svi oni imaju pristup .NET okruenju, ve mogu i meusobno komunicirati. Sasvim je
mogue kod programiranja u jeziku C# koristiti kod napisan u Visual Basic .NET-u, kao i obrnuto.
Sve ovo omoguuje dosad nezamisliv nivo viestruke namene, to pored ostalog ini .NET
okruenje toliko atraktivnim.

ta se nalazi unutar .NET okruenja?


.NET okruenje se najveim delom sastoji od ogromne biblioteke koda koju upotrebljavamo
preko klijentskih jezika (kao to je C#) koristei tehnike objektno orijentisanog programiranja
(OOP). Ova biblioteka podeljena je na razliite module koje koristimo u zavisnosti od zadatka. Na
primer, jedan modul sadri delove potrebne za pravljenje Windows aplikacija, drugi je vezan za
mree, a neki za razvoj Weba. Neki moduli su podeljeni u razliite podmodule, kao to su moduli za
pravljenje Web servisa unutar modula za razvoj Weba.
Namera je da razliiti operativni sistemi podravaju neke ili sve module zavisno od njihovih
karakteristika. Na primer PDA e imati podrku za sve osnovne funkcionalnosti .NET modula, to se
svakako ne odnosi i na one namenske ili rede koriene.
Jedan deo biblioteke .NET okruenja definie samo osnovne tipove. Tip je u stvari nain na koji se
predstavlja podatak (kao to je recimo oznaena 32-bitna celobrojna veliina), a definicijom
fundamentalnih tipova podataka olakava se interoperatibilnost izmedu jezika koji koriste .NET *
okruenje. To se naziva zajedniki sistem tipova (engl. Common Type System - CTS).
Okruenje osim biblioteke poseduje i .NET zajedniko izvrno jeziko okruenje (engl.
Common Language Runtime - CLR), koje je odgovorno za izvravanje svih aplikacija razvijenih uz
pomo :NET biblioteke.

Kako napisati aplikaciju koristei .NET okruenje?


Pisanje aplikacija unutar .NET okruenja u stvari znai pisanje koda (koristi se bilo koji jezik koji
podrava ovo okruenje) uz pomo .-NET biblioteke koda. U ovoj semestru koristiemo VS za razvoj,
koji je mono i integrisano razvojno okruenje koje podrava jezik C# . Prednost ovog okruenja
je lakoa kojom se mogunosti .NET-a mogu integrisati u na kod. Kod koji emo pisati bie u
potpunosti C#, ali demo koristiti .NET okruenje, a takoe i dodatne alate VS-a kada zatreba.
Da bi se C# kod izvrio neophodno ga je prevesti u jezik koji operativni sistem na kome je
aplikacija razume, poznat kao prirodni kod. Ovo prevoenje se jo naziva i kompajliranje koda,
funkcija koju obavlja kompajler. Unutar .NET okruenja ta operacija ima dve faze.

MSIL i JIT
Kada kompajliramo kod koristei biblioteku .NET okruenja, ne pravimo odmah prirodni kod
specifian za operativni sistem. Umesto toga, kompajliramo u Microsoftov posredni jezik (engl.
Microsoft Intermediate Language - MSIL). Ovaj kod nije odreen ni jednim operativnim sistemom i
nije namenjen samo za jezik C#. Ostali .NET jezici - na primer, Visual Basic .NET - takoe se
kompajliraju u njega u svojoj prvoj fazi. VS e izvesti ovaj korak ukoliko ga koristimo pri razvoju C#
aplikacija.
Da bi se program izvrio, oigledno je potrebno jo rada. Za taj posao zaduen je
kompajler u pravo vreme (engl. Just-In-Time - JIT), koji prevodi MSIL u prirodni kod
specificiran od strane operativnog sistema i arhitekture same maine na kojoj se program
izvodi. Tek tada operativni sistem moe izvriti program. Pojam u pravo vreme" oznaava
da se MSIL kod kompajlira samo kada je to potrebno.
U prolosti je bilo neophodno kompajlirati kod u vise razliitih aplikacija zavisno od samog
operativnog sistema i arhitekture samog procesora. esto je to bio oblik optimizacije (da
2

bi se recimo kod naterao da radi bre na AMD setu ipova), ali s vremena na vreme moglo
je biti kritino (da aplikacije, na primer rade i pod Win9x i pod WinNT/2000 okruenjima).
Sve je to sada nepotrebno, jer JIT kompajleri (kako im samo ime kae) koriste MSIL kod,
koji je nezavisan od maine, operativnog sistema ili procesora. Postoji nekoliko JIT
kompajlera - svaki za razliitu arhitektura, a koristie se odgovarajui da bi se napravio
traeni prirodni kod.
Lepota je u tome to je mnogo manje rada potrebno sa nae strane. U stvari, moemo
zaboraviti na detalje koji se odnose na sistemsku zavisnost i koncentrisati se na mnogo
zanimljiviju funkcionalnost naeg koda.

Sklopovi
Kada kompajliramo aplikaciju, MSIL kod se smeta u posebne sklopove (engl. assembly).
Takvi sklopovi sadre i izvrne programske datoteke koje mogu biti startovane direktno iz
Windowsa bez potrebe za nekim drugim programima (takve datoteke imaju .exe nastavak) i
biblioteke koje koriste i druge aplikacije (koje imaju . dll nastavak).
Sklopovi pored MSIL sadre i takozvane meta informacije (odnosno podatke o podacima
sadranim u sklopu, nazvane jo i metapodaci), kao i opcione resurse (dodatne podatke
koje koristi MSIL, kao to su zvukovi i slike). Metapodaci dozvoljavaju sklopovima da budu
potpuno samoopisujui. Ne trebaju nam nikakve dodatne informacije da bi smo koristili
sklopove. Podrazumeva se, naravno da izbegnemo situacije kao to su nedostavljanje
traenih informacija sistemskom registru i si., to je inae esto bio problem pri korienju
drugih platformi.
To u stvari znai da je distribucija aplikacija esto jednostavna koliko i kopiranje podataka
u direktorijum na nekom udaljenom raunaru. Kako nam nisu potrebne nikakve
dodatne informacije o ciljnim sistemima, moemo odmah pokrenuti izvrnu datoteku
iz ovog direktorijuma i (pod uslovom da je .NET CLR instaliran) poleemo.
Naravno da neemo uvek eleti da ukljuimo sve to je potrebno za izvrenje jedne
aplikacije na jednom mestu. Moda poelimo da napiemo kod koji e moi da koriste i druge
aplikacije. U tom sluaju korisno je takav vienamenski kod smestiti na mesto koje mogu
koristiti sve aplikacije U .NET okruenju to mesto se naziva globalni ke sklopova (engl.
Global Assembly Cache - GAC). Smetanje koda u ovaj ke je jednostavno - samo postavimo
programski skup koji sadri ovaj kod u direktorijum koji sadri ke.

Upravljivi kod
Uloga CLR-a se ne zaustavlja onog trenutka kada smo kompajlirali kod u MSIL, niti kada JIT
kompajler sve to prevede u prirodni kod. Kod napisan u .NET okruenju je upravljiv tokom
svog izvrenja (ova faza se obino naziva izvrna). To znai da CLR vodi rauna o naoj
aplikaciji kroz upravljanje memorijom, obezbeivanje sigurnosti, dozvoljava meujeziko
otklanjanje greaka i tako dalje. Suprotno ovome, aplikacije koje ne rade pod kontrolom
CLR-a nazivaju se neupravljive, odreeni jezici kao to je C++ mogu se koristiti za pisanje
takvih aplikacija ( na primer, da bi se pristupilo funkcijama niskog stepena operativnog
sistema). Sve u svemu, u jeziku C# moemo napisati samo onaj kod koji radi pod upravljivim
okruenjem. Mi demo iskoristiti razne mogunosti upravljivosti CLR-a i dozvoliti .NET-u da se
sam pozabavi interakcijom sa operativnim sistemom.

Sakupljanje otpada
Jedna od najvanijih mogunosti upravljivog koda jeste koncept sakupljanja otpada. Ovo je
metod .NET-a koji se stara o tome da memorija koju je aplikacija koristila tokom svog
izvrenja bude obavezno ispranjena kada aplikacija nije vise u upotrebi. Pre pojave .NET-a
to je najee bila briga samih programera, te je usled nekoliko malih greaka memorija
misteriozno gubila itave blokove jer bila pogreno pozivana. To je najee bilo praeno
usporavanjem vaeg raunara i obaveznim padom sistema.
Sakupljanje otpada se odvija tako to uestalo ispituje memoriju vaeg raunara i odbacuje
sve to vam nije vise potrebno. Ono nema neki vremenski okvir izvravanja, moe se dogoditi
hiljadu puta u sekundi, jednom u nekoliko sekundi, ili kad god, ali moete biti sigurni da e
se dogoditi.
Kako je sakupljanje otpada nepredvidivo, morate ga imati na umu dok radite aplikacije. Kod
koji za svoje izvrenje zahteva puno memorije morao bi iza sebe da poisti pre nego to
dopusti sakupljanju otpada da to uradi za njega, ali to nije tako teko kako zvui.

Uklapanje u celinu
Pre nego to nastavimo, sumirajmo sve korake koji su nam potrebni da bi smo napravili .NET
aplikaciju.
1. Kod za aplikaciju pie se korienjem .NET kompatibilnog jezika kao to je C#:

2. Ovaj kod se kompajlira u MSIL, koji je smeten u sklop:

3. Kod koji se izvrava (bez obzira da li je sam po sebi izvrni ili ga koristi neki drugi kod) mora
se prethodno kompajlirati kroz JIT kompajler u prirodni kod:

4. Prirodni kod se izvrava u kontekstu upravljanog CLR, zajedno sa bilo kojom drugom
aplikacijom ili procesom:

Povezivanje
Postoji jedan dodatak gore pomenutom procesu. C# kod koji se kompajlira u MSIL u koraku 2
ne mora da bude smeten u jednu datoteku. Mogue je podeliti kod aplikacije u razliite
datoteke koji e se tokom kompajliranja objediniti u sklop. Ovaj proces je poznat i kao
povezivanje i veoma je koristan. Ta podela se vri jer je mnogo lake raditi sa vise manjih
datoteka nego sa jednom ogromnom. Moete izdeliti kod na logike celine i smestiti ih u
nezavisne datoteke na kojima se moe nezavisno raditi i praktino zaboraviti na njih kada
zavrite. Ovo nam olakava pronalaenje odreenih delova koda kada nam zatrebaju. Takoe
omoguuje programerskim timovima da podele teret na manje delove kojima je lake
rukovati, kao i to da ukoliko doe do provere nekog od tih delova ne postoji rizik da se
ugroze celina programa ili njegovi delovi na kojima se radi.
Takoe celo MSJIT kompajliranje moe se predstaviti i u celini to vam moe pomoi da
sagledate na drugi nain:

ta je C# ?
Kako je gore pomenuto, C# je jedan od jezika koji slui za izradu aplikacija koje mogu raditi
pod .NET CLR-om. On predstavlja evoluciju jezika C i C++ koju je kreirao Microsoft da bi se
radilo sa .NET okruenjem. U njegovom razvoju koriene su mnoge prednosti drugih
jezika, naravno uz otklanjanje njihovih mana.
Razvoj aplikacija u jeziku C# je jednostavniji nego u C++, jer je sintaksa prostija. Pa ipak,
C# je moan jezik i postoji veoma mali broj stvari koje bi smo uradili u C++ jeziku pre nego
u C#-u. Paralelne mogunosti jezika C# onima naprednijim u C++-U, kao to je direktno
pristupanje i manipulisanje sistemskom memorijom, moe biti izvedeno jedino kroz kod koji
je obeleen kao nesiguran. Ove napredne tehnike programiranja su potencijalna opasnost
(odakle im i ime) zato to je mogue pristupiti memorijskim blokovima koji su kritini za
sistem, a sve to potencijalno vodi ka katastrofi. Iz ovog razloga, kao i drugih, ova tema nije
obraena ovim predavanjima.
S vremena na vreme kod u jeziku C# je malo razumljiviji od C++ koda. Jer je C# jezik
sigurniji po pitanju dodele tipa promenljivim (za razliku od C++-a). To znai da ukoliko nekoj

promenljivoj ili nekom podatku dodelimo odreeni tip, on ne moe biti zamenjen nekim
drugim nevezanim tipom. Postoje stroga pravila kojih se moramo pridravati prilikom
konverzija tipova, to u sutini znai da emo esto morati da napiemo vise koda u jeziku C#
nego u C++-U da bismo izvrili iste zadatke. Ali iz toga moemo izvui i neku korist. Kod je
robusniji i jednostavnije je otkloniti greke, odnosno .NET u svakom trenutku moe
odrediti kojem tipu pripada traeni podatak.
Usled toga jezik C# nam ne omoguuje naredbe kao to su Uzmi deo memorije poevi od
4. bajta unutar podatka i duine 10 bajta i interpretiraj ga kao X", to ne mora da bude
uvek loe.
C# je samo jedan od jezika koji omoguuju rad sa .NET razvojnim okruenjem, ali moda je
i najbolji. Njegova prednost je u tome to je jedini napravljen od poetka ba za .NET
okruenje, pa samim rim moe biti i vodei jezik korien za verzije .NET-a namenjene
dragim operativnim sistemima. VB.NET je, recimo, napravljen tako da bude to sliniji
svojim prethodnicima i stoga ne moe da iskoristi .NET biblioteku koda u potpunosti.
Suprotno njemu, jezik C# je napravljen tako da moe iskoristiti svaki deo biblioteke koda
.NET okruenja koju ova moe da ponudi.

Kakve aplikacije moemo pisati u C#-u?


Kako je gore navedeno, jezik C# nema ogranienja u pogledu toga kakve sve aplikacije
moemo napraviti. C# koristi okruenje i samim tim nema ogranienja u vezi sa moguim
aplikacijama. Pa ipak, pogledajmo koji su tipovi najee pravljenih aplikacija:
Windows aplikacije - To su recimo, aplikacije tipa Microsoft Office koje imaju
izgled Windowsa i odlino se slau sa njim. Ovo je uproeno korienjem modula
Windows formulara unutar .NET okruenja, koji u stvari ini biblioteka
kontrola (kao to su dugmad, palete alatki, meniji i tako dalje) koje nam koriste
pri izradi Windows korisnikog interfejsa (UI).
Web aplikacije - Web strane koje moemo videti kroz bilo koji ita. .NET
okruenje prua veoma moan sistem generisanja Web sadraja i to dinamiki,
dozvoljavajui personalizaciju, sigurnost i jo mnogo toga. Ovaj sistem se naziva
Active Server Pages .NET (ASP.NET), a jezik C# moemo koristiti za izradu
ASP.NET aplikacija uz pomo Web formulara.
Web servisi - Predstavljaju nov i uzbudljiv nain izrade raznovrsnih
distribuiranih aplikacija. Koristei Web servise preko Interneta moemo
razmenjivati bilo koju vrstu podataka, koristei prostu sintaksu, ne vodei rauna o
tome u kom jeziku je napisana aplikacija niti na kom sistemu je postavljena.
Bilo kom od ovih tipova moe zatrebati pristup bazama podataka, to se postie
korienjem Active Data Objects .NET (ADO.NET) odeljka .NET okruenja. Mnogi od
ovih resursa mogu biti iskorieni, kao to su alati za izradu komponenata na mrei,
iscrtavanje, izvoenje komplikovanih matematikih zadataka i tako dalje.

Visual Studio.NET
U ovom predavanju za programiranje u jeziku C# koristimo Visual Studio .NET (VS),
poev od aplikacija koje se pokreu iz komandne linije, pa sve do kompleksnih tipova
projekata. VS nije neophodan za razvoj C# aplikacija, ali nam znatno olakava stvari.
Moemo (ako to poelimo) napisati na kod u najobinijem programu za ureivanje teksta,
kao to je Notepad, i kompajlirati kod u sklopove koristei kompajler iz komandne linije
koji je u sastavu .NET okruenja. Meutim, zato bismo to radili, kada moemo iskoristiti
snagu VS-a da nam pomogne?
Sledi kratka lista razloga zbog kojih je VS pravi izbor za razvoj u .NET okruenju:
VS automatizuje korake neophodne pri kompajliranju prirodnog koda, ali u isto
vreme dozvoljava i kompletnu kontrolu nad opcijama ukoliko elimo da ih
promenimo.
VS program za ureivanje teksta je povezan sa jezicima koje podrava VS
(ukljuujui jezik C#) i to tako da omoguuje pametnu detekciju greaka i sugerie
odgovarajui kod na pravom mestu dok ga unosimo.
VS sadri i dizajnerske alate za aplikacije koje ukljuuju Windows formulare kao i
Web formulare, koji vam omoguuju jednostavna tehnika povlaenja i putanja
(engl. drag-and-drop) dizajn elemenata korisnikog interfejsa.
Mnogi tipovi projekata koji su mogui u jeziku C# mogu se napraviti sa,
'optenamenskim' kodom koji se ve nalazi na pravom mestu. Umesto da poinjemo
od nule, esto emo nai razliite datoteke koje sadre kod koji je za nas zapoet,
smanjujui nam vreme provedeno u spremanju projekta.
VS sadri nekoliko arobnjaka koji vam automatizuju zadatke opte namene i koji
mogu dodati odgovarajui kod postojeim datotekama, a da mi o tome ne vodimo
brigu (ili u nekim sluajevima ak i da ne pamtimo tanu sintaksu).
VS sadri mone alatke za prikazivanje i navigaciju elemenata naeg projekta, bez
obzira da li se radi o prirodnom kodu jezika C# ili nekoj slici, ili moda zvunoj
datoteci.
Pored toga to olakava pisanje aplikacija, VS omoguuje i jednostavniju distribuciju i
prilagoavanje projekata klijentima, kako bi ih oni lake koristili ili instalirali.
VS omoguuje i napredne tehnike otklanjanja greaka pri razvoju projekata, i to tako da
moemo u isto vreme ui u kod jedne instrukcije dok pazimo u kakvom je stanju aplikacija.
Ima jo mnogo toga, ali nadam se da ste shvatili o emu se radi!

Reenja u VS-u
Kada koristimo VS za razvoj aplikacija, to radimo kreiranjem reenja. Reenje, po VS
terminologiji, predstavlja neto vise od aplikacije. Reenja sadre projekte, koji mogu
biti zasnovani na Windows formularima, Web formularima i tako dalje. Reenja mogu
sadrati i vise projekata, tako da moemo grupisati srodan kod na jedno mesto, iako e se
oni kompajlirati u razliite sklopove na razliitim mestima na disku.
Ovo moe biti od velike koristi, kada se radi na deljenom kodu (koji moe biti smeten u
globalni ke sklopova) u isto vreme dok aplikacije koriste taj kod. Otklanjanje greaka u
kodu je mnogo lake ako se koristi jedinstveno razvojno okruenje, jer moemo pratiti
instrukcije u viestrukim modulima koda.

Saetak
U ovom predavanju upoznali smo se sa osnovnim pojmovima .NET razvojnog okruenja i sa
mogunostima pravljenja monih i raznovrsnih aplikacija. Saznali smo ta je neophodno da
bi se kod napisan, recimo, u jeziku C# pretvorio u funkcionalnu aplikaciju, i koje su
prednosti upravljanog koda koji radi pod optim izvrnim jezikom .NET-a (Common Language
Runtime).
Videli smo ta je u stvari jezik C#, kako je povezan sa .NET okruenjem i upoznali se sa
alatom koji emo koristiti za programiranje u C# - Visual Studio .NET-u.
U sledeem predavanju nauiemo kako se C# kod pie pomou VS-a, pa emo samim tim moi
da se skoncentriemo na jezik C# sam po sebi, umesto da brinemo o tome kako VS radi.

Pisanje programa u jeziku C#


Nakon to smo se upoznali sa tim ta je u stvari jezik C# i kako se uklapa u .NET okruenje,
doao je trenutak da zaponemo sa pisanjem koda. U tom poslu koristiemo Visual Studio
.NET (VS), pa treba da nauimo osnovne stvari o torn razvojnom okruenju. VS je ogroman i
komplikovan proizvod, tako da u prvo vreme korisniku moe delovati zastraujue, ali uz
njegovu pomo pravljenje jednostavnih aplikacija moe biti iznenaujue prosto. im
ponemo sa korienjem VS-a uvideete da nije potrebno mnogo znati o njemu da bismo se
poigrali sa C# kodom. Kasnije emo videti neke mnogo komplikovanije operacije koje je
mogue izvesti u VS-u, ali za sada su dovoljna osnovna znanja.
Poto zavirimo u VS, sastaviemo dve proste aplikacije. Za sada se neemo mnogo
optereivati kodom, samo emo se upoznati sa tim koje su procedure potrebne da bi se
aplikacija napravila i da bi funkcionisala kako treba, mada e sve to uskoro postati sporedno.
Prva aplikacija koju emo napraviti bie jednostavna konzolna aplikacija. Konzolne aplikacije
ne koriste grafiko okruenje Windowsa, tako da ne moramo da brinemo o dugmadima,
menijima, interakciji sa pokazivaem mia i tako dalje. Umesto toga, pokrenuemo
aplikaciju iz komandne linije i komunicirati sa njom na mnogo prostiji nain.
Druga aplikacija e biti bazirana na Windows formularima. Njen izgled, kao i rad sa njom,
bie vrlo prepoznatljiv onima koji su koristili Windows i njeno kreiranje ne zahteva nita
vise rada nego prethodna. Ipak, sintaksa njenog koda je mnogo komplikovanija, mada esto
neemo morati da vodimo rauna o detaljima.
Dodatna fleksibilnost Windows aplikacija nije neophodna da bi se nauio C# jezik, dok
jednostavnost konzolnih aplikacija omoguuje da se skoncentriemo na uenje sintakse, a
da za to vreme ne brinemo o tome kako aplikacija izgleda niti kakav je oseaj raditi sa njom.

Razvojno okruenje Visual Studio .NET


Kada prvi put uitate VS, odmah se pojavi nekoliko prozora, od kojih je veina prazna,
zajedno sa nizom elemenata menija i ikona sa paletama alatki.
Ukoliko prvi put pokreete VS bie vam predstavljena lista sa vrednostima namenjena za
korisnike sa iskustvom u radu na prethodnim izdanjima ovog razvojnog okruenja.
Automatski odabrani element! su sasvim u redu, za sada ih prihvatite jer tu nema niega to
se kasnije ne moe promeniti.
Izgled VS okruenja je u potpunosti prilagodljiv, ali su nam sasvim dovoljne ve postavljene
vrednosti. One su sreene na sledei nain:

Glavni prozor, koji prikazuje uvodnu poetnu stranu" kada se VS pokrene, jeste onaj u
kome se prikazuje ceo na kod. Ovaj prozor je podeljen na kartice tako da moemo lako
skakati sa jedne na drugu datoteku tako to emo pritisnuti miem njihovo ime. Ovaj
prozor ima i druge funkcije: moe prikazati grafiki korisniki interfejs koji dizajniramo za
na projekat, iste tekstualne datoteke, HTML, kao i razliite alate ugraene u VS.
Opisaemo svaki, kako na njega naiemo tokom rada.
Iznad glavnog prozora nalaze se palete sa alatkama, kao i VS meni. Ovde moete nai
nekoliko razliitih paleta sa alatkama rangiranih po funkcionalnosti - od alatki za snimanje i
uitavanje datoteka, preko izgradnje i pokretanja projekta, do kontrola za otklanjanje
greaka. O svima njima emo priati kada nam budu zatrebali.
Slede kratki opisi glavnih karakteristika VS-a, koje ete najee koristiti:
Server Explorer i Toolbox paleta sa alatkama izbacuju sopstvene menije kada se preko njih
prede miem, i otvaraju nam nove dodatne mogunosti, kao to su pristup i podeavanje
karakteristika i servisa samog servera, i pristup korisnikom interfejsu za izradu elemenata
Windows aplikacija.
Solution Explorer prozor prikazuje informacije o trenutno uitanim reenjima. Reenje je
po terminologiji VS-a jedan ili vise projekata zajedno sa njihovom konfiguracijom. Ovde
moemo videti razliiti pogled na projekte unutar reenja, kao to su datoteke iz kojih se
sastoje i njihov sadraj.
Properties prozor omoguuje detaljniji pogled na sadrinu projekta i dozvoljava nam da
izvedemo dodatno konfigurisanje pojedinih elemenata. Na primer, taj prozor moemo
koristiti da promenimo izgled dugmeta unutar Windows formulara.
Task List and Output prozor prikazuje informacije prilikom kompajliranja projekta zajedno
sa zadacima koji treba da se izvre (slino listi zadataka u Microsoft Outlooku). Ovi zadaci se
mogu uneti runo, a mogu biti i automatski generisani od VS-a.

Ponimo sa pravljenjem prvog primera naeg projekta, koji e u sebe ukljuiti mnogo VS
elemenata koje smo gore naveli.

Konzolna aplikacija
U ovom predavanju koristiti
napravimo jednu jednostavnu.

emo konzolne aplikacije, posebno na poetku, stoga

Veba br. 1.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:

Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Console Application u okviru prozora Templates: (za ovo ete morati malo da pomerite
prozor
na
dole).
U
okviru
za
tekst
Location:
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba1 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: Pozdrav
Svete.

Pritisnite miem na dugme OK.


Kada se projekat inicijalizuje dodajte sledee redove u datoteku koja se bude pojavila u
glavnom prozora:

Izaberite Debug | Start Without Debbuging iz menija. Posle nekoliko trenutaka trebalo bi
da vidite sledee:

Pritisnite bilo koji taster da izaete iz aplikacije.


Takoe samu konzolnu aplikaciju moemo pokrenuti i na drugi nain:
Odaberite Start | Programs | Microsoft Visual Studio .NET 2003 | Visual Studio .NET
Tools | Visual Studio .NET Command Prompt. Pojavie se komandni prozor i bie
definisane sve promenljive okruenja potrebne prevodiocima i alatkama Visual Studija.
Ako se pokrene obino komandno okruenje, bez zadavanja tih promenljivih, .NET alatke
nee raditi.

Posle otvaranja komandnog prozora .NET-a uite u folder u kome ste sauvali ovu konzolnu
aplikaciju. Unesite u komandnom prozoru sledeu komandu, koja prevodi kod konzolne
aplikacije:
csc Class.cs <Enter>
Naravno programiranje pod celim Visual Studio .NET je tkz. Case Sensity, osetljiv velika i mala
slova. Tako da morate da obratite panju pri kucanju koda. Ovde to nije sluaj, ali nije
naodmet da se navikavate na velika i mala slova.
Prvo ete dobiti obavetenje o verziji prevodioca i izvrnog okruenja, a zatim i o autorskim
pravima. Pokrenute program i biete pozdravljeni na sledei nain:
C:\> Class1
Pozdrav svete na jeziku C# !
C:\>
Funkcija Console.WriteLine() dodaje tekstu indikator novog reda (engl. Newline character). U
windowsu je to kombinacija znaka za poetak reda i znaka za prelazak u novi red. Da biste u
nekoliko iskaza pisali u istom redu, koristite funkciju Write(). Ona zahteva da sami dodate
indikator novog reda. Sada u prethodnom programu zamenite iskaz WriteLine() sledeim iskazima:
Cons ol e. Writ e (" Zdr av o sv e t e " ) ;
Console.Write ( " n a jeziku C # ! \ r \ n " ) ;
Obrnuta kosa crta (\) ispred znaka je signal prevodiocu da je u pitanju izlazna sekvenca (engl.
escape sequence). Iz sledee tabele vidi se da C# koristi iste izlazne znake kao i C++.
Ako iza obrnute kose crte stavite neki dragi znak, dobiete od prevodioca poruku da nije
prepoznao izlazni znak.
Izlazna sekvenca
\a
\b
V
\n

Znaenje
Zvono. Zvunik proizvodi kratak signal.
Brisanje ulevo (engl. backspace). Pomera za jedno mesto ulevo.
Kraj strane. Pomera na poetak sledee strane prilikom
tampanja. Na ekranu daje kontrolni znak.
Novi red. Pomera u sledei red. Na ekranu se kursor pomera na
poetak sledeeg reda.

Znak za povratak na poetak reda. Pomera na poetak tekueg


reda. Tekst koji se ispisuje na ekranu posle ovog znaka,
pojavljivae se preko tekueg sadraja reda.

\t

Horizontalan tabulator. Daje znak tabulatora.

\v

Vertikalan tabulator. Pomera kursor nadole za zadati broj


redova. Na ekranu daje kontrolni znak.

\"

Navodnici. Bez obrnute kose crte se koristi kao graninik za


znakovne nizove. U kombinaciji sa obrnutom kosom crtom,
prevodilac ga tumai kao obian znak.

\\

Dvostruka obrnuta kosa crta. Ispisuje obrnutu kosu crtu.

Kako to radi
Za sada neemo ispitivati kod koji smo koristili u ovom projektu; vise demo brinuti o tome kako
koristiti VS da bi se kod osposobio za izvravanje. Kao to ste videli, VS radi gomilu stvari za nas, to
ini jednostavnim proces kompajliranja i izvrenja koda. Postoji vise naina za izvoenje ak i ovako
jednostavnih koraka. Na primer, pravljenje novog projekta moe se izvesti preko stavke menija
File| New | Project... kao to smo i radili, ili pritiskanjem kombinacije tastera Ctrl+Shift+N, ili
pritiskom miem na odgovarajuu ikonu u paleti sa alatkama.
Slino tome va kod moe biti kompajliran i izvren na vise naina. Za metod koji smo koristili
izborom stavke menija Debug | Start Without Debbuging, imamo takoe preicu (Ctrl+F5), a isto
tako i ikonu u paleti sa alatkama. Kod moemo pokrenuti korienjem stavke menija Debug | Start
(takoe pritiskajui F5 ili odabirajui odgovarajuu ikonu; ili moemo kompajlirati kod bez njegovog
pokretanja (sa ukljuenom ili iskljuenom proverom greaka) koristei Build | Build, Ctrl+Shift+B,
ili odabirajui drugu ikonu. Kada je kod kompajliran moemo ga pokrenuti startovanjem dobijene
.exe datoteke iz Windows Explorera, ili iz komandne linije.
Da bismo to izveli, moramo otvoriti komandnu liniju, prei u direktorijum
C:\Temp\SoftIng\LecturesCode\Vezba1\bin\Debug\, uneti Pozdrav Svete i pritisnuti
taster Enter.
U narednim primerima samo emo rei: Napravite novi konzolni projekat", ili: Pokrenite
program", a vi izaberite nain koji vam odgovara da biste to uradili. Ukoliko ne bude
drugaije naglaeno, kod treba pokretati sa ukljuenim otklanjanjem greaka.
Treba naglasiti da se poruka Press any key to continue koju ste videli u okviru konzolnog
programa, pojavljuje samo ukoliko nije ukljueno ispravljanje greaka. Ako pokrenemo
projekat u modu za otklanjanje greaka prozor konzolnog programa e nestati. U principu to
je dobro, ali ne i za prethodni primer. Ukoliko bismo tako uradili, ne bismo videli rezultate
naeg rada.
Sada smo napravili projekat preko koga moemo detaljno pogledati neke delove ovog
projektnog okruenja.
Prvi prozor na koji treba obratiti panju je Solution Explorer | Class View u gornjem desnom
uglu ekrana koji je dole prikazan u oba reima rada (reim moete menjati pritiskajui
dugmad u dnu prozora).

Ovaj pogled preko Solution Explorera prikazuje datoteke od kojih se sastoji projekat
Pozdrav svete. Datoteka kojoj smo dodali kod je Class1.cs prikazana zajedno sa jo jednom
kod datotekom, AssemblyInfo.cs. (Sve datoteke sa C# kodom imaju nastavak cs). Ova druga
datoteka sa kodom za sada nije naa briga, ona sadri dodatne informacije o naem projektu
koje nas se jo uvek ne tiu.

Unutar ovog prozora moemo menjati sadraj glavnog prozora, koji e se kod unutar njega
prikazivati, i to tako to emo otvoriti datoteku .cs koja nam je potrebna ili pritisnuti na nju
desnim dugmetom mia i odabrati opciju View Code.
To moete uraditi i na drugi nain, jednostavnim pritiskom miem na dugme iz palete sa
alatkama u gornjem delu prozora. U okviru ovog prozora moemo i manipulisati sa
datotekama, brisati ih, menjati im ime i slino.
Ovde se takoe mogu nalaziti i drugi tipovi datoteka, kao to su resursne datoteke projekta
(resursi su datoteke koje nisu uvek C# datoteke - to mogu biti i slike ili zvune datoteke).
Naravno, i sa njima moemo manipulisati preko istog interfejsa.
Lista References sadri spisak .NET biblioteka koje koristimo u naem projektu. I to je neto
ime emo se pozabaviti kasnije, zato to su standardne reference za na poetak dovoljne.
Drugi pogled istog prozora, Class View, predstavlja nain da pogledamo na projekat kroz
strukturu koda koji smo napravili. Tome emo se vratiti kasnije, a za sada odaberimo pogled
Solution Explorer.
Primetiete da se sadraj donjeg prozora menja u odnosu na to koju ikonu ili datoteku
odaberete u gornjim prozorima. To je jo jedan prozor koji ima vise pogleda, ali najvaniji
od njih je pogled Properties:

Ovaj prozor pokazuje dodatne informacije o tome ta smo odabrali u prozora iznad njega.
Na primer, kada izaberemo Class1.cs iz naeg projekta videemo ono to je prikazano na
slici. Ovaj prozor moe da nam prikae i informacije o drugim elementima koje odaberemo,
kao to su komponente korisnikog interfejsa, to emo videti u drugom delu ovog
predavanja koji se bavi Windows aplikacijama.
esto, ukoliko unesemo izmene u prozor Properties, to e direktno uticati na kod tako to e
dodati nove redove koda ili menjati sadraj naih datoteka. U nekim projektima proveemo
isto toliko vremena menjajui stvari u ovom prozora, koliko emo provesti u pisanju samog
koda.
Sada pogledajmo prozor Output. Kada ste pokretali program verovatno ste primetili da se u
ovom prozora pojavio neki tekst pre konzolnog prozora nae aplikacije. Na naem raunara
pojavilo se, na primer:

Kao to moete pretpostaviti, to je izvetaj o statusu datoteka koje se kompajliraju. Ovde


emo dobiti i izvetaj o grekama koje se mogu dogoditi tokom kompajliranja. Na primer,
probajte da obriete taku-zarez iz reda koji smo dodali unosei kod u prethodnom koraku, i
ponovo kompajlirajte. Ovaj put videete sledee:

Ovaj put projekat nee raditi.


U sledeem predavanju kada budemo preli na sintaksu C#-a, videemo da se taka-zarez
oekuje kroz ceo kod - na kraju skoro svakog reda naeg koda.
Poto sada moramo neto uraditi da bismo naterali kod da radi, VS automatski dodaje
zadatak u listu zadataka koja deli prostor sa prozorom Output:

Ovaj prozor e nam pomoi da utvrdimo gde se u naem kodu nalaze greke i vodie rauna
o tome ta sve treba da uradimo da bi kompajlirali na kod. Ako dva puta pritisnemo miem
na greku prikazanu u ovom prozoru, kursor e se postaviti tano na mestu gde je greka
unutar koda (otvorie se datoteka koda koja sadri greku ukoliko ve nije otvorena), tako
da problem moemo brzo reiti. Takoe emo videti male crvene talasaste linije na mestu
gde lei naa greka tako da kod nije teko pretraiti.
Zapazite kako je lokacija greke navedena kao broj reda. VS program za ureivanje teksta
standardno ne prikazuje brojeve redova, a to je neto to bi bilo od koristi da vidimo. Da
bismo to postigli, trebalo bi potvrditi odreena polja za potvrdu unutar dijaloga Options do
koga se dolazi izborom stavke menija Tools | Options.... Ime polja za potvrdu je Line
Numbers i nalazi se u kategoriji Text Editor | C# | General, kao to je prikazano na
sledeoj slici:

10

Promenljive i izrazi
Raunarski program je, najpreciznije reeno, serija operacija koja manipulie podacima. To
vai i za najkomplikovanije primere kao to su obimne i vienamenske Windows aplikacije
(Microsoft Office, na primer). Najee skriven od pogleda korisnika, taj skup operacija se
uvek odvija u pozadini.
Ono to vidite na vaem monitoru toliko vam je poznato, da je teko zamisliti da je cela pria
neto vise od pokretnih slika". U stvari, ono to vidite jeste samo predstava nekih
podataka, ija gruba forma nije nita drugo do niz nula i jedinica smetenih negde u
unutranjosti memorije vaeg raunara. Sve to uradite na ekranu, bez obzira na to da li se
radi o pokretanju pokazivaa mia, pritiska na neku ikonu, ili unosa teksta u program za
ureivanje teksta, rezultirae naizmeninom razmenom podataka u memoriji.
Naravno, postoje i manje apstraktne situacije koje vam mogu pokazati isto. Ukoliko
ukljuite aplikaciju kalkulator, obezbediete podatke u obliku brojeva i izvesti odreene
operacije sa njima na nain na koji biste to uradili i na papiru, samo to je ovako mnogo
bre.
Ako je raunarski program u osnovi izvoenje operacija nad podacima, to znai da je
nama potreban nain na koji moemo uskladititi neke podatke, kao i utvrivanje metoda
manipulacije njima. Ove dve funkcije se obezbeuju preko promenljivih i izraza
respektivno, a u ovom predavanju istraiemo ta to uopteno i detaljno znai.
Prethodno je potrebno da se upoznamo sa osnovnom sintaksom jezika C#.

Osnove C# sintakse

Izgled i oseaj rada sa jezikom C# vrlo je slian C++-u i Javi. U poetku sintaksa izgleda
prilino zbunjujue, a i manje je nalik pisanom engleskom nego neki drugi jezici. Pa ipak,
kako zaponete sa programiranjem u jeziku C# shvatiete da je sintaksa razumljiva i da je
mogue napisati vrlo jasan i itljiv kod bez mnogo muke.
Za razliku od kompajlera za neke druge jezike, C# kompajler ne obraa panju na dodatne
razmake unutar koda, bez obzira na to da li se sastoje od blanko znakova, tabulatora ili
znakova za novi red. To znai da imamo prilinu slobodu u formatiranju naeg koda, iako se
pridravanjem odreenih pravila itanje koda moe znatno olakati.
C# kod je sastavljen od niza iskaza, a svaki od njih se zavrava takom-zarezom. Kako se
beli (prazan) prostor ignorie, mogue je u jedan red staviti vise iskaza, ali zarad itljivosti
uobiajeno je prei u novi red nakon take-zareza. Na taj nain izbegavamo vise iskaza u
jednom redu. Savreno je prihvatljivo (ak i prilino normalno) da se jedan iskaz unese u
vise redova.
C# spada u jezike sa blokovskom strukturom, to znai da su svi iskazi delovi bloka unutar
koda. Ovi blokovi, koji su oivieni vitiastom zagradom ({i}), mogu da sadre bilo koju vrstu
iskaza, a i ne moraju ni jednu. Zapamtite da vitiaste zagrade ne zahtevaju taku-zarez iza
sebe.
Na primer, blok C# koda moe izgledati ovako:
{

<red koda 1, iskaz 1 >;


<red koda 2, iskaz 2 >
<red koda 3, iskaz 3>;

Ovde naravno <red koda x, iskaz y> nisu pravi izgled C# koda - kroz ovaj tekst je samo
prikazano gde bi trebalo staviti C# iskaze. Primetite da su u ovom sluaju red 2 i red 3 deo
istog iskaza zbog toga to na kraju reda dva ne postoji taka-zarez.

U ovom jednostavnom primeru nain na koji je uvuen tekst tipian je za C#. To nije
izmiljeni metod pisanja C# koda, ve ustaljena praksa; VS e sam uraditi slinu stvar.
Uopteno, svaki blok koda ima svoj stepen uvlaenja, koliko e desno biti postavljen u
odnosu na levu ivicu. Blokovi koda mogu biti ugnedeni jedan u drugi (odnosno, blokovi
mogu sadrati druge blokove), i u torn sluaju se ugnedeni blokovi uvlae jo vie:
{
<red koda 1>;
{
<red koda 2>;
<red koda 3>;
}
<red koda 4>;
}
Takoe, redovi koda koji predstavljaju nastavak prethodnog reda uvlae se jo vise, kao u
prvom primeru u redu 3.
Zapamtite da ovaj stil pisanja niim nije uslovljen. Meutim, ukoliko ga ne koristite, stvari
mogu postati vrlo konfuzne!
Jo jedna stvar koju esto nalazimo u C# kodu jesu komentari. Komentari, strogo govorei,
uopte nisu deo C# koda, ali na svu sreu postoje unutar njega. Komentari rade ono to im
ime kazuje: omoguavaju dodavanje opisnog teksta vaem kodu - i to na srpskom
(engleskom, francuskom, nemakom, mongolskom i tako dalje) jeziku, a to e kompajler u
potpunosti ignorisati. Kada se budemo bavili nekim delovima koda koji su dui, bie zgodno
da dodamo podsetnike o tome ta radimo, na primer: Ovaj red koda pita korisnika za broj",
ili: Ovaj deo koda je napisao Petar". C# sadri dva naina da se to izvede. Moemo postaviti
markere na poetku i na kraju komentara, ili moemo upotrebiti marker koji oznaava da je
sve do kraja ovog reda komentar. Ovaj poslednji metod je izuzetak od pravila koje smo gore
pomenuli, da C# kompajler ignorie prelazak u novi red.
Za obeleavanje komentara prvom metodom koristimo znakove / * " na poetku
komentara, i znakove * / " na kraju. Ovo moete koristiti za jedan red i za vise njih, ali u
torn sluaju svi redovi izmedu markera postaju deo komentara. Jedina stvar koju ne
moemo unositi unutar markera jeste * / ", jer bi to bilo shvaeno kao kraj komentara.
Tako da je prihvatljivo sledee:
/* Ovo je komentar */
/* Takoe...
... i ovo */
Ali sledee bi izazvalo probleme:
/* Komentari se cesto zavravaju " */" znakovima */
Ovde e kraj komentara (znakovi posle * / ") biti prepoznat kao C# kod i doi e do greke.
Drugi pristup komentarima ukljuuje zapoinjanje komentara znakom / / ". U nastavku
moete unositi ta god vam je volja sve dok ste u istom redu! Sledee ispravno:
// Ovo je druga vrsta komentara.
Ali, sledee nee raditi, zato to e drugi red biti interpretiran kao C# kod:
// Takoe je i ovo,
ali ovo nije.

Ova vrsta komentara je korisna za dokumentovanje iskaza, jer moe biti postavljena u istom
redu kao i iskaz:
<Iskaz>; // Objanjenje iskaza
Trei tip komentara u jeziku C# dozvoljava vam da dokumentujete va kod. To su
pojedinani redovi komentara koji poinju sa tri / " simbola umesto sa dva, na primer:
/// Poseban komentar
Pod normalnim okolnostima kompajler ignorie ovakve komentare kao i sve druge, ali VS
moete konfigurisati tako da on pravi posebno formatirane tekstualne datoteke kada se
projekat kompajlira, koje nam kasnije mogu koristiti da napravimo prateu dokumentaciju.
Vrlo je vano naglasiti da je C# kod osetljiv na upotrebu malih i velikih slova. Za razliku od
nekih drugih jezika, kod se mora unositi pazei na upotrebu velikih i malih slova. Ukoliko se
toga ne pridravamo, zaustaviemo kompajliranje projekta.

Osnove strukture C# konzolne aplikacije

Pogledajmo
jo
jednom
primer
konzolne
aplikacije
iz
prethodnog
predavanja (Pozdrav Svete), i zavirimo u njegovu strukturu. Kod je izgledao ovako:
using System;
namespace Pozdrav_Svete
{
/// <summary>
/// Summary description for Class1.
/// <summary>
class Classl1
{
static void Main(string [] args)
{
//
// TODO: Add code to start application here
//
Console.WriteLine("Pozdrav svete na jeziku C# !");
}
}
}
Moemo odmah uoiti sve elemente sintakse o kojima smo malopre priali. Vidimo takuzarez, vitiaste zagrade, komentare zajedno sa odgovarajuim uvlaenjem.
Najvaniji deo koda za sada je:
static void Main (string [] args)
{
//
// TODO: Add code to start application here
//
Console.WriteLine("Pozdrav svete na jeziku C# !");
}
Ovaj deo koda se izvrava kada se konzolna aplikacija startuje, ili jo preciznije, izvrava se
blok koda oivien vitiastim zagradama. Jedini red koda koji e neto uraditi jeste onaj koji
smo dodali automatski generisanom kodu - to je u stvari jedini red koji nije komentar. Ovaj
kod jednostavno ispisuje neki tekst unutar konzolnog prozora, iako nas trenutno ne
interesuje taan mehanizam kojim se to izaziva.

Cilj nam je da u prvih nekoliko predavanja objasnimo osnove sintakse jezika C#, tako da nas
ne interesuje kako u toku svog izvravanja aplikacija dolazi do take gde se poziva
Console.WriteLine (). Kasnije emo razjasniti znaaj ovog dodatnog koda.

Promenljive

Kako je naznaeno u uvodu ovog predavanja, promenljive nam slue da u njih skladitimo
podatke. U osnovi, o promenljivima unutar memorije raunara razmiljamo kao o malim
kutijama koje su poreane u nekoj polici. Te kutije moemo puniti raznim stvarima i
prazniti ih, ili moemo samo zaviriti u njih.
Iako u osnovi svi raunarski podaci u sutini sadre istu stvar (nizove jedinica i nula),
promenljive imaju vise tipova. Ponovo kroz analogiju sa kutijama moemo zamisliti da one
dolaze u razliitim veliinama i oblicima, tako da odreene stvari mogu stati samo u
odreene kutije. Glavni razlog za ovakav nain raspodele po tipovima lei u tome to
postoje razliiti tipovi podataka kojima se na drugaiji nain manipulie, tako da
ograniavajui promenljive po tipu izbegavamo zabunu. Na primer, ne bi bilo logino
tretirati na isti nain nizove jedinica i nula koje zajedno ine digitalnu sliku kao i zvune
datoteke.
Da bismo koristili promenljive, one moraju biti deklarisane. To znai da moramo da im
dodelimo ime i tip. Jednom kad ih deklariemo, koristiemo ih za smetanje onog tipa
podataka koji je naznaen u deklaraciji.
Da bi se promenljiva navela u jeziku C# koristi se tip i ime kao u sledeem primeru:
<tip> <ime>;
Ako probamo da upotrebimo promenljivu koja nije deklarisana, kod se nee kompajlirati, ali
u torn sluaju kompajler e vas tano obavestiti ta je problem. Pored toga, ako pokuate
da upotrebite promenljivu kojoj niste dodelili neku vrednost, to e takoe prouzrokovati
greku, ali kompajler e i to primetiti.
injenica je da postoji neogranien broj tipova koje moemo koristiti. To nam omoguava
da sami definiemo svoje tipove ma koliko zamreni oni bili.
Kada smo ve kod toga, postoje odreeni tipovi podataka koje e svi poeleti da koriste u
odreenom trenutku, na primer promenljive koje sadre brojeve. Iz tog razloga postoje
prosti unapred definisani tipovi promenljivih koje bi trebalo znati.

Prosti tipovi promenljivih

Prosti tipovi su recimo brojevne ili logike vrednosti (tano ili netano) koje sainjavaju
osnovne blokove za izgradnju naih aplikacija, kao i za izgradnju drugih, sloenijih tipova.
Veina prostih tipova su brojevni, to nam u prvi mah izgleda malo udno - zar nam ne treba
samo jedan tip promenljivih da bismo uskladitili brojeve?
Razlog za podelu tipova brojevnih promenljivih lei u samom mehanizmu smetanja brojeva
kao nizova jedinica i nula u memoriju raunara. Za celobrojne vrednosti jednostavno
uzimamo odreen broj bitova (nezavisnih cifri koje mogu biti jedinice ili nule) i
predstavljamo na broj u binarnom formatu. Promenljiva koja smeta N bitova dozvoljava
nam da preko nje prikaemo bilo koji broj izmedu 0 i (2n- 1). Bilo koji broj iznad ove
vrednosti bie prevelik da se smesti u
promenljivu. Recimo da imamo promenljivu u koju moemo smestili dva bita. Preslikavanje
izmedu celih brojeva i bitova koji ih predstavljaju izgleda ovako:
0=00
1=01
2-10
3-11

Ako elimo da smestimo vise brojeva, treba nam vise bitova (tri bita e nam recimo,
omoguiti smetanje brojeva od 0 do 7).
Nezaobilazan zakljuak bi bio da nam za sve brojeve koje moemo zamisliti treba
beskonana koliina bita, to ba i nee stati u na verni PC. ak i da postoji odgovarajui
broj bitova za svaki broj, nikako ne bi bilo efikasno koristiti sve bitove za, recimo,
promenljivu koja treba da smesti u sebe brojeve od 0 do 10 (ogroman prostor bi bio
protraen). etiri bita bi nam ovde zavrila posao, dozvoljavajui nam da u isti memorijski
prostor smestimo znatno vise vrednosti iz ovog opsega.
Umesto toga, imamo odreen broj razliitih celobrojnih tipova koje demo koristiti za
razliite opsege brojeva, ime emo zauzimati i razliite koliine memorije (sve do 64 bita).
Sledi njihova lista:
Zapamtite da svaki od ovih tipova koristi jedan ili vie standardnih tipova definisanih u
.NET okruenju. Kao to smo razmotrili u prvom predavanju, korienje standardnih
tipova nam omoguuje kombinovanje vise razliitih jezika u jedan projekat ili reenje. Nazivi
koje koristimo za tipove u jeziku C# predstavljaju pseudonime za tipove koji su definisani u
okruenju. Ova tabela je lista imena ovih tipova, i onoga ta predstavljaju unutar biblioteke
.NET okruenja.
Tip

pseudonim za

dozvoljene vrednosti

sbyte

System.SByte

ceo broj izmeu -128 i 127.

byte

System.Byte

ceo broj izmeu 0 i 255.

short

System.Intl6

ceo broj izmeu -32768 i 32767.

ushort

System.UIntl6

int

System.Int32

uint

System.UInt32

long

System.Int64

ulong

System.UInt64

ceo broj O i 65535.


ceo broj izmeu -2147.483.648 i 2147.483.647.
ceo broj izmeu 0 i 4294967295.
ceo broj izmeu -9223.372.036.854.775.808
i 9223.372.036.854.775.807.
ceo broj izmeu 0 i 1846.744.073.709.551.615.

Znak u" koji stoji ispred imena nekih promenljivih jeste skraenica za unsigned"
(neoznaeno), to znai da u taj tip promenljivih ne moemo smetati negativne brojeve,
to se moe videti iz kolone dozvoljenih vrednosti u prethodnoj tabeli.
Pored celobrojnih, potreban nam je i nain da smestimo brojeve sa pokretnim zarezom,
odnosno decimalne brojeve. Postoje tri tipa promenljivih namenjenih brojevima sa
pokretnim zarezom: float, double i decimal. Prva dva tipa uvaju brojeve u pokretnom
zarezu u obliku +/- m x 2e, gde se dozvoljene vrednosti za m i e razlikuju za svaki tip. Tip
decimal koristi oblik +/- m x 10e. Ova tri tipa, zajedno sa dozvoljenim vrednostima, kao i
realnim opsezima, prikazani su u sledeoj tabeli:
Tip

Pseudonim za

Minm

Maxm

Mine

Maxe

Pribl. min
vrednost

Pribl. max
vrednost

float

System. Single

224

-149

104

1.5x10-45

3.4x1038

double

System.Double

253

-1075

970

5.0x10124

1.7x10308

decimal

System.Decimal

296

-26

1.0x10-28

7.9x1028

Pored brojevnih tipova postoje jo tri prosta tipa:


Tip

Pseudonim za

char

System.Char

bool

System.Boolean

string

System.String

Dozvoljene vrednosti
pojedinaan Unicode znak, smeten kao ceo broj izmeu
0 i 65535.
logika vrednost, true ili f a l s e .
niz znakova.

Zapazite da ne postoji gornja granica za niz znakova koji sainjavaju string. To je zbog toga
to koliina memorije koju on zauzima moe biti promenljiva.
Logiki tip bool je jedan od najee korienih tipova promenljivih u jeziku C#. Slini tipovi
se najee koriste i u drugim jezicima. Vrlo je vano imati promenljivu koja moe imati
vrednosti true ili false, zbog logikog toka aplikacije. Uzmite u razmatranje, na primer, na
koliko pitanja moe biti odgovoreno sa true ili false (odnosno, sa da ili ne). Poreenje
vrednosti dve promenljive ili potvrivanje nekog unosa podataka, predstavljaju samo dva od
mnogih naina primene logikih promenljivih koje emo uskoro isprobati.
Poto smo se upoznali sa tipovima promenljivih, uradimo kratak primer kako ih deklarisati i
koristiti.

Veba br. 2.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:

Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Console Application u okviru prozora Templates: (za ovo ete morati malo da pomerite
prozor
na
dole).
U
okviru
za
tekst
Location:
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba2 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: Rad sa
promenljivima1.

Dodajte sledei kod u Classl.cs (obriite redove sa komentarom na torn mestu):

Pokrenite program (ukoliko vam nije iskljuen reim za otklanjanje greaka, konzolna
aplikacija e se zatvoriti pre nego to vidite ta se dogodilo):

Kako to radi
Kod koji ste dodali uradi sledee:
deklarie dve promenljive;
dodeljuje vrednosti promenljivima;
preko konzole ispisuje te dve vrednosti.

Promenljive se deklariu u sledeem kodu:


int MojInteger;
string MojString;
Prvi red deklarie promenljivu tipa int i to pod imenom MojInteger, a dragi red deklarie
promenljivu tipa string nazvanu MojString.
Zapamtite da je dodeljivanje imena promenljivima ogranieno, odnosno ne moe ba sve biti ime
promenljive. O ovome emo priati u delu koji se bavi imenovanjem promenljivih.

Sledea dva reda koda deklariu vrednosti:


MojInteger = 17;
MojString = "Moj Ceo Broj \"MojInteger\" je:";
Ovde dodeljujemo dve fiksne vrednosti (poznatije kao vrednosti literala unutar koda) naim
promenljivima koristei operator dodele = (o operatorima emo detaljnije govoriti u delu koji
se bavi izrazima u okviru ovog predavanja). Dodeljujemo vrednost 17 promenljivoj MojInteger,
dok promenljivoj MojString dodeljujemo MojInteger" is (ukljuujui i navodnike). Kada se
dodeljuju znakovne vrednosti literala, zapamtite da moraju biti oiviene navodnicima. Da bi
se to izvelo kako treba, neke znakove ne smemo koristiti unutar navodnika (na primer-same
navodnike), ili ih moramo oznaiti tako to emo umesto njih koristiti neki niz znakova (poznat
kao escape sekvenca) koji predstavlja one koje elimo da koristimo.
U ovom primeru koristili smo sekvencu \" da bismo oznaili duple navodnike:
MojString = "Moj Ceo Broj \"MojInteger\" je:";
Da nismo koristili escape sekvencu, i umesto nje probali:
MojString = ""MojInteger" je";
pri kompajliranju bi se pojavila greka.
Pri dodeljivanju znakova literala moramo biti oprezni sa prelazima u novi red - C# kompajler
e odbaciti literale koji su vei od jednog reda. Ako elimo da proirimo literal na vise od
jednog reda, moramo koristiti escape sekvencu \n. Na primer, sledea dodela:
MojString = "Ovaj string ima \nprelazaka u novi red. ";
bie prikazana u dva reda u okviru konzolnog prozora.
Sve iskone (engl. escape) sekvence sastoje se iz znaka obrnute kose crte ( \ ) koji prati
nekoliko znakova (videemo kasnije koji su to znakovi). Poto je znak obrnute kose crte
iskorien u ovu svrhu, i za njega postoji escape sekvenca koja se jednostavno sastoji iz dva
takva znaka, \\.
Vratimo se kodu. Ostao nam je samo jo jedan red koji nismo prouili:
Console.WriteLine("{0} {1}.", MojString, MojInteger);

Ovo je jako slino metodi ispisivanja teksta unutar konzole koju smo koristili u prvom primeru,
ali smo sada naveli i nae promenljive. Ovo je tehnika koju emo koristiti u prvom delu knjige
da bismo u okviru konzolnog prozora ispisali neki tekst. Unutar zagrada imamo dve stvari:
string,
listu promenljivih ije vrednosti elimo da ubacimo u izlazni string,
odvojenu zarezima.
ini se da string koji ispisujemo na izlazu, " {0} {1}. ", ne sadri nikakav koristan tekst. Ali
kada se program pokrene, vidimo da taj string u stvari predstavlja ablon u koji ubacujemo
sadraj naih promenljivih. Svaki znak oivien vitiastim zagradama predstavlja mesto na koje
se smeta sadraj naih promenljivih. A svako mesto (ili string za formatiranje) predstavljeno
je celobrojnom vrednou oivienom vitiastim zagradama. Celobrojne vrednosti poinju od
nule i uveavaju se za jedan, a ukupan broj mesta treba da bude jednak broju promenljivih
koje su navedene u produetku stringa i odvojene su zarezima. Kada se tekst ispie na konzoli,
svako mesto biva zamenjeno odgovarajuom vrednou predviene promenljive. U gore
navedenom primeru { 0 } je zamenjena stvarnom vrednou prve promenljive MojString, a {1}
je zamenjeno sadrajem promenljive MojInteger.
Ovaj metod ispisa teksta na konzolu koristiemo i u narednim primerima.

Imenovanje promenljivih, konvencije


i vrednosti literala
Kao to je spomenuto u prethodnom delu, za ime promenljive ne moe se koristiti bilo koji
niz znakova. I pored toga, ostaje nam dovoljno fleksibilan nain imenovanja promenljivih.
Osnovna pravila pri imenovanju promenljivih su:
Prvi znak imena promenljive mora biti ili slovo, ili znak podvlaenja (_), ili @.
Naredni znakovi mogu biti slova, znakovi podvlaenja ili brojevi.

Kao dodatak tome postoje odreene kljune rei koje oznaavaju neke radnje samom
kompajleru, kao to su kljune rei using i namespace iz prethodnih primera. Ako kojim
sluajem iskoristimo neku od kljunih rei kao ime promenljive, kompajler e se pobuniti, i
ubrzo ete shvatiti da ste napravili greku, pa stoga ne brinite o tome mnogo.
Na primer, sledea imena promenljivih su dobra:
myBigVar
VAR1
_test

Ova nisu:
99FlasaPiva
namespace
Sve-je-gotovo

Upamtite, C# je osetljiv na korienje velikih i malih slova, zbog ega moramo


pamtiti taan oblik imena koje smo dodelili promenljivoj. ak i jedna greka ovog
tipa spreie kompajliranje programa.
Posledica toga je i to da moemo imati vie promenljivih koje se razlikuju samo u velikim i
malim slovima. Na primer, ovo su sve razliite promenljive:
myVariable
MyVariable
MYVARIABLE

Pravila imenovanja
Imena promenljivih su neto sa ime ete mnogo raditi. Zbog toga bi vredelo malo vremena
utroiti na neku optu klasifikaciju i sortiranje imena koja emo koristiti. Pre nego to
krenemo trebalo bi da imate na umu da je ovo kontroverzna oblast. Tokom godina razliiti
sistemi su dolazili i odlazili, a neki programeri se svojski bore da opravdaju sopstvene sisteme.
Do skoro najpopularniji sistem bio je poznat kao maarska notacija. U njemu svaka
promenjiva sadri prefiks koji se pie malim slovom i identifikuje tip. Na primer, ako je
promenljiva tipa int onda stavljamo i ( ili n) ispred njenog imena (recimo iGodiste). Koristei
ovaj sistem, lako se moe utvrditi kog su tipa promenljive.
Primena tog sistema u modernijim jezicima kao to je C#, malo je nezgodna. Za one tipove
promenljivih koje smo do sada upoznali, mogli bismo se lako snai sa jednim ili dva slova kao
prefiksima. Ali poto sami moemo definisati kompleksnije tipove, a i kako postoji vise stotina
kompleksnih tipova u osnovi .NET okruenja, taj sistem brzo postaje neupotrebljiv. Kako na
jednom projektu moe raditi vise ljudi, svaki od njih moe za sebe pronai posebnu
1

kombinaciju oznaka za prefikse i na taj nain potpuno zbuniti ostale, to dovodi do pogubnih
posledica.
Programeri su do sada shvatili da je najbolje imenovati promenljivu prema njenoj nameni. Ako
iskrsne bilo kakva sumnja, dovoljno je lako pronai kome tipu promenljiva pripada. U VS-u
dovoljno je da pokaziva mia namestimo na ime promenljive kojoj elimo da otkrijemo tip i
ispisae se poruka koja nas o tome obavetava.
Trenutno imamo dve konvencije prema kojima se promenljive imenuju u .NET okruenju, a to
su PascalCase i camelCase.
Nain na koji su napisana imena ove dve konvencije je prema njihovoj upotrebi: obe se odnose
na to da imena promenljivih budu sastavljena iz vie rei, a i naglaavaju da svaka re poinje
velikim slovom, dok su sva ostala mala. Konvencija camelCase ima dodatno pravilo - da prvo
slovo kompletnog imena promenljive bude malo slovo.
Sledei primer koristi camelCase konvenciju:
godite
imeUenika
datumUpisa

A u sledeem je upotrebljena konvencija PascalCase:


Godite
PrezimeUenika
ZimaNaegNezadovoljstva

Za proste promenljive pridravaemo se konvencije camelCase, dok demo PascalCase koristiti


za naprednije imenovanje, to je u stvari preporuka Microsofta.
Konano, vredi napomenuti da su sistemi imenovanja u prolosti esto koristili znak
podvlaenja, obino da bi se odvojile rei unutar imena promenljivih, kao to je
moja_prva_promenljiva. Ovakav pristup je sada odbaen.

Tabela 4.1. Prefiksi tipova podataka

Tip podataka

Prefiks

Primer vrednosti

Boolean
Byte
Char
Decimal
Double
Integer
Long
Object

bln
byt
chr
dec
dbl
int
lng
obj

blnUlogovan
bytGodiste
chrLozinka
decProdato
dblRezultatIzracunavanja
intBrojacPetlje
lngIdKupca
objWord

Short

sho
str

shoTotalnaVrednost
strIme

String

Tabela 4.2. Prefiksi promenljivih po podruju vaenja

Podruje vaenja
Global
Private to class
Nonstatic promenljiva, local to
method

Prefiks

Primer vrednosti

g
m

g_strSnimiPutanju
m_blnPromenaVrednosti

(no prefix)

Vrednosti literala
U prethodnom primeru videli smo dve vrednosti literala - celobrojnu i znakovnu. I drugi tipovi
promenljivih takoe mogu imati vrednosti literala, to e biti prikazano u sledeoj tabeli.
Mnogi od njih ukljuuju sufikse, odnosno nizove znakova koji se dodaju na kraju literala da bi
se naznaio eljeni tip. Neki literali imaju vie razliitih tipova koje na osnovu konteksta
odreuje kompajler za vreme kompajliranja:
Tabela 4.3. Sufiksi literala kod tipova podataka

Tip(ovi)

Kategorija

Sufiks

bool
int,uint, long, ulong
uint,ulong
long, ulong

logika
celobrojna
celobrojna
celobrojna

ulong

celobrojna

float
double
decimal
char

realna
realna
realna
znakovna
niz znakova

nema
nema
u ili U
l ili L
ul, uL, Ul,lu,
U, Lu, ili LU
f ili F
nema, d ili D
m ili M
nema

string

nema

Primer/dozvoljene vrednosti
true ili false
100
100U
100L
100UL
1.5F
1.5
1.5M
a, ili escape sekvenca
a..a, moe se ukljuiti escape
sekvenca

String literali
Ranije u ovom predavanju videli smo nekoliko iskonih sekvenci koje moemo koristiti u
literalnim stringovima. Vredi predstaviti kompletnu tabelu, da bismo imali podsetnik:

Tabela 4.4. Escape sekvence

Escape sekvenca

Znak koji pravi

Vrednost znaka u unicode-u

\`
\"
\\
\0
\a

jednostruki navodnik

0x0027
0x0022
0x005C
0x0000
0x0007

dvostruki navodnik
obrnuta kosa crta
nula
alarm(pravi pitanje)

Tabela 4.4. Escape sekvence

Escape sekvenca
\b
\f
\n
\r
\t
\v

Znak koji pravi

Vrednost znaka u unicode-u

unazad za jedan znak

0x00080
0x000C
0x000A
0x000D
0x0009
0x000B

prelazak na sledeu stranicu


novi red
prenos u novi red
horizontalni tabulator
vertikalni tabulator

Kolona ove tabele koja prikazuje Unicode vrednost, predstavlja heksadecimalnu vrednost koju
taj znak ima u Unicode skupu znakova.
Za svaki Unicode znak moemo navesti odgovarajuu iskonu sekvencu, kao to su one u
tabeli. Sekvenca se uvek sastoji od znaka \ iza koga sledi etvorocifrena heksadecimalna
vrednost (na primer etiri cifre iza znaka x u gornjoj tabeli).
To znai da su sledea dva stringa ekvivalentna:
"Petar\s string."
"Petar\u0027s string"

Oigledno da imamo vise mogunosti korienjem Unicode iskorienih sekvenci.


Takoe moemo deformisati i literalne stringove. To podrazumeva da su u taj niz ukljueni svi
znakovi oivieni dvostrukim navodnikom, ukljuujui i one koji oznaavaju kraj reda ili iskonu
sekvencu. Jedini izuzetak je iskona sekvenca za dvostruke navodnike koja se mora navesti da bi
se izbegao prevremeni kraj niza. Da bi se ovo izbeglo, na poetak niza znakova, pre navodnika,
stavljamo znak @:
@"sinonim string literala."

Niz znakova, odnosno string, lako moemo deformisati na normalan nain, ali sledei zahteva
ovaj metod:
@"Kratka lista:
objekat 1
objekat 2"

Literalni stringovi naroito su korisni u imenima datoteka zato to ovi esto koriste znak obrnute
kose crte. Ako koristimo normalan string, moramo koristiti dvostruku obrnutu kosu crtu u celom
stringu, na primer:
"C: \Temp\MojFolder\MojFajl.doc"

Sa litaralnim stringom, ovo moe biti itljivije. Sledei literalni string predstavlja potpuno isto
kao malopreanji niz znakova:
@"C:\Temp\ MojFolder\MojFajl.doc"

Zapamtite da su nizovi znakova, odnosno stringovi, referentnog tipa, za razliku od onih koji su vrednosnog tipa
Posledica toga je i to da se stringu moe dodeliti vrednost null, to znai da string promenljiva ne pokazuje na
string. Ovo emo kasnije detaljnije objasniti.

Odreivanje i dodeljivanje vrednosti promenljivim


Setimo se da smo deklarisali promenljive koristei samo njihov tip i ime, na primer:
int godite;

Potom smo joj dodelili vrednost uz pomo operatora dodele =:


godite = 25;
Upamtite da promenljive moraju biti inicijalizovane pre nego to ih upotrebimo. Prethodni redovi mogu biti
korieni kao inicijalizacija.

Ima jo nekoliko stvari koje moemo uraditi, koje ete vidati u C# kodu. Prvo, moemo navesti
vise razliitih promenljivih istog tipa u isto vreme, to je mogue izvesti ako ih odvojimo
zarezom:
int xVelicina, yVelicina;

gde su i xVelicina i yVelicina obe navedene kao celobrojne promenljive.


Druga tehnika koju ete sretati jeste dodeljivanje vrednosti promenljivima dok ih deklariemo,
to u stvari znai kombinovanje dva reda koda:
int godite = 25;

A moemo i obe tehnike koristiti zajedno:


int xVelicina =4, yVelicina = 5;

Ovde su xVelicina i yVelicina razliitih vrednosti. Pogledajte sledee:


int xVelicina, yVelicina = 4;

Ovo znai da je yVelicina inicijalizovana, a xVelicina samo deklarisana.

Izrazi
Videli smo kako deklarisati i inicijalizovati promenljive i vreme je da nauimo kako da sa njima
manipuliemo. C# kod sadri vei broj operatora koji tome slue, ukljuujui i operator
dodeljivanja =, koji smo ve koristili. Kombinovanjem operatora sa promenljivima i literalima
(koji se nazivaju operandi kada se koriste zajedno sa operatorima) moemo formirati izraze, koji
ine osnovne gradivne blokove pri raunanju.
Postoji irok dijapazon operatora, od onih jednostavnih do najkomplikovanijih, koje ete sretati
samo u matematikim primenama. Prosti ukljuuju sve osnovne matematike operacije, kao to
je; recimo operator + za sabiranje, a oni komplikovaniji, na primer, manipulaciju nad sadrajem
promenljive i to prikazane u binarnom obliku. Postoje i logiki operatori koji slue u radu sa
logikim promenljivima, kao i operatori dodele, recimo =.

U ovom predavanju skoncentrisaemo se na matematike i operatore dodeljivanja, dok emo za


idua ostaviti logike operatore. Naime, preko logikih emo ispitivati kontrolu toka programa.
Operatori se mogu grubo podeliti na tri kategorije:
unarni operatori, koji rade samo sa jednim operandom;
binarni operatori, koji rade sa dva operanda;
ternarni operatori, koji rade sa tri operanda.
Najvei deo operatora spada u binarne, samo nekoliko u unarne, dok je ternarni samo jedan koji
se jo zove i uslovni operator (uslovni operator je logiki, odnosno on vraa logiku vrednost, ali
o tome u iduem predavanju).
Pogledajmo sada matematike operatore, koji sadre i binarnu i unarnu kategoriju.

Matematiki operatori
Postoji pet prostih matematikih operatora, od kojih dva imaju i unarnu i binarnu formu. U
donjoj tabeli navedeni su svi ove operatori, zajedno sa kratkim primerom njihove upotrebe i
rezultatima pri radu sa prostim numerikim tipovima (celobrojnim i decimalnim):

Tabela 4.5. Operatori

Operator

Kategorija

Primer izraza

Rezultat

binarni

var1=var2+var3;

binarni

var1=var2-var3;

binarni

var1 = var2 * var3;

binarni

var1 = var2 / var3

binarni

var1 = var2 % var3

+
-

unarni

var1 = +var2

var1 je dodeljena vrednost sume


var2 i var3
var1 je dodeljena vrednost razlike
var2 i var3
var1 je dodeljena vrednost
proizvoda var2 i var3
var1 je dodeljena vrednost deljenja
var2 i var3
var1 je dodeljena vrednost koja je
ostatak deljenja var2 i var3
var1 je dodeljena vrednost var2

unarni

var1 = -var2

var1 je dodeljena vrednost var2

Primeri su pokazani korienjem prostih numerikih tipova. Ukoliko koristite druge proste tipove
moe doi do zabune. Sta mislite da e se dogoditi ako, na primer, saberete dve logike
promenljive ? U ovom sluaju nita, zato to e se kompajler odmah pobuniti ako, recimo,
pokuate da koristite operator + (ili bilo koji dragi matematiki operator) sa bool promenljivama.
Sabiranje dve promenljive tipa char takoe dovodi do malog nesporazuma. Zapamtite da se
promenljive tipa char uvaju kao brojevi, pa prema tome, sabiranje takve dve promenljive za
rezultat daje broj (da budemo precizniji, broj tipa int). Ovo je primer implicitne konverzije i o
njemu emo jo dosta govoriti, kao i o eksplicitnoj konverziji, koja se takoe odnosi na
sluajeve kada su var1, var2, i var3 razliitih tipova.

Nakon ovoga, binarni + operator ima smisla koristiti sa promenljivama tipa string. U ovom sluaju
tabela treba ovako da izgleda:
Tabela 4.6. Operatori

Operator

Kategorija

binarni

Primer izraza
var1=var2+var3;

Rezultat
var1 je dodeljena nadovezana
vrednost stringova var2 i var3

Nijedna draga matematika operacija nee raditi sa stringovima.


Ostala dva operatora koje treba da upoznamo su operatori inkrementiranja i dekrementiranja.
Oba su unarni operatori koji se koriste na dva razliita naina: ili odmah ispred, ili odmah iza
operanda. Pogledajmo na brzinu rezultate ovih prostih izraza, pa ih onda razmotrimo:
Tabela 4.7. Operatori inkrementiranja i dekrementiranja

Operator

Kategorija

Primer izraza

++

unarni

var1=++var2

--

unarni

var1=--var2

++

unarni

var1=var2++

--

unarni

var1=var2--

Rezultat
var1
var2
var1
var2
var1
var2
var1
var2

je
je
je
je
je
je
je
je

dodeljena vrednost. var2+1,


uveana za 1.
dodeljena vrednost. var2-1,
umanjena za 1.
dodeljena vrednost var2.
uveana za 1.
dodeljena vrednost var2.
umanjena za 1.

Kljuna stvar kod ovih operatora je da se vrednost operanda uvek menja. ++ uvek uveava svoj 1
operand za 1, a - ga uvek umanjuje za 1. Od toga gde se operator tano nalazi, zavisi i rezultat
koji je smeten u var1. Smetanje operatora pre operanda, znai da se operand menja pre nego
to se izvre dalja izraunavanja. Ukoliko ih stavimo posle operanda, operand se menja tek posle
izraunavanja.
Ovo zahteva jo jedan primer. Razmotrite sledei kod:
int var1, var2 = 5, var3=6;
var1 = var2++* --var3;

Pitanje je sledee: koja e vrednost biti dodeljena promenljivoj var1 ? Pre nego to se izraz
izrauna, operator -- e promeniti vrednost var3 iz 6 u 5. Operator ++ koji stoji posle var2,
moemo ignorisati, jer se on nee izvriti pre nego to se obavi raunanje, tako da e var1 biti
proizvod 5 i 5, odnosno 25.
Prosti unarni operatori mogu nam koristiti u mnogim situacijama. Oni su u stvari samo skraenica
za izraze tipa:
var1 =var1+ 1;

Ovaj tip izraza ima mnogo upotreba, pogotovo kada se radi o petljama.

Preko sledeeg primera videemo kako da koristimo matematike operatore i upoznaemo se sa


nekim novim, korisnim konceptima.

Veba br. 3.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Console Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor
na dole). U okviru za tekst Location: promenite putanju u
C:\Temp\SoftIng\LecturesCode\Vezba3 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: Promenljive2
Dodajte sledei kod u Class1.cs:

Operatori dodeljivanja

Do sada smo koristili prost operator dodele =, i moda vam je iznenaujue da bilo koji drugi
postoji. Meutim, ima ih vise i mogu biti vrlo korisni! Svi ostali operatori dodele rade na slian
nain. Kao i kod operatora = i drugi se dre toga da se promenljiva kojoj se dodeljuje vrednost
nalazi sa leve strane, dok se operandi i operatori nalaze sa desne strane. Kao i ranije videemo
tabelarni prikaz njihovih objanjenja:

Snimite program, i pokrenite ga.

Unesite vae ime i pritisnite Enter. Zatim unesite potrebne brojeve, i pritiskajte Enter.

Kako to radi

Osim to nam prikazuje operatore, ovaj kod nam donosi dva vana koncepta sa kojima emo se
susresti mnogo puta u radnim primerima:
Korisniki unos
Konverzija tipa
Korisniki unos je slian komandi Console.WriteLine (), koju smo ve videli. Ovde, meutim,
koristimo Console.ReadLine(). Ova komanda trai od korisnika neki unos, koji smeta u
promenljivu tipa string:

Ovaj kod ispisuje sadraj dodeljene promenljive, userName, pravo na ekran. U ovom primera
uitavamo i dva broja. Ovo je malo kompleksnije, zato to Console.ReadLine() generie string,
a nama treba broj. Ovo nas uvodi u temu konverzije tipa. O ovome emo detaljnije u
kasnije, za sada pogledajmo kod iz primera. Prvo, navodimo dve promenljive u koje treba
smestiti brojeve koje unosimo:

Sledee, ispisujemo poruku i koristimo komandu Convert.ToDouble() na promenljivoj tipa string


koju nam je vratio red Console.ReadLine(), da bismo konvertovali promenljivu iz tipa string u tip
double. Ovaj broj dodeljujemo promenljivoj prviBroj koju smo naveli:

Ova sintaksa je izuzetno prosta, a verovatno vas nee zauditi kada saznate da se mnoge druge
konverzije odvijaju na slian nain. I drugi broj dobijamo na isti nain:

Potom na izlaz aljemo rezultate sabiranja, oduzimanja, mnoenja, deljenja, i na kraju


prikazujemo ostatak posle deljenja, koristei operator modula (%) za to:

U oit e da su izrazi prviBroj + drugiBroj i slino, parametri iskaza Console.


WriteLine( ) , bez korienja neke posredne promenljive:

Ovakva sintaksa omoguuje veliku itljivost koda, i smanjuje broj redova koje moramo da
napiemo.

10

Operatori dodeljivanja
Do sada smo koristili prost operator dodele =, i moda vam je iznenaujue da bilo koji
drugi postoji. Meutim, ima ih vise i mogu biti vrlo korisni! Svi ostali operatori dodele rade
na slian nain. Kao i kod operatora = i drugi se dre toga da se promenljiva kojoj se
dodeljuje vrednost nalazi sa leve strane, dok se operandi i operatori nalaze sa desne strane.
Kao i ranije videemo tabelarni prikaz njihovih objanjenja:
Tabela 4.8. Operatori dodeljivanja

Operator

Kategorija

Primer izraza

Rezultat

=
+=
-=
*=
/=
%=

binarni

var1=var2;
var1+=var2
var1-=var2;
var1*=var2;
var1/=var2;
var1%=var2;

var1 je dodeljena vrednost var2


var1 je dodeljena vrednost koja ini sumu v a r1 v ar2
var1 je dodeljena vrednost razlike varl i var2
var1 je dodeljena vrednost proizvoda v a r 1 i var2
var1 je dodeljena vrednost deljenja var1 i var2
var1 je dodeljena vrednost ostatka deljenja var1 i var2

binarni
binarni
binarni
binarni
binarni

Kao to vidite, dodatni operatori ukljuuju var1 u izraunavanje, tako da:


var1 += var2;

daje isti rezultat kao i:


var1 = var1 + var2;

Upamtite da se operator += moe koristiti i sa stringovima, kao i +.


Ukoliko koristimo dugaka imena za promenljive, ovi operatori nam mogu nainiti kod itljivijim.

Prvenstvo operatora

Kada raunar obrauje izraz, on izvrava svaki operator prema redosledu. Meutim, to ne znai
da se operatori uvek izraunavaju sleva nadesno.
Jednostavan primer je:
var1 = var2 + var3;
Ovde se prvo izvrava operator + pa tek onda =.
Postoje i druge situacije kada prvenstvo izvoenja operatora nije oigledno, na primer:
var1 = var2 + var3 * var4;
Ovde je redosled izvrenja sledei: prvo operator * , zatim + i na kraju =. Ovo je
standardni matematiki redosled i daje isti rezultat kao da ste na papiru izveli neku operaciju
u algebri. Kod takvih kalkulacija, moemo odrediti prvenstvo izvravanja koristei zagrade, na
primer:
var1 =

(var2 + var3)

* var4;

11

Ovde se sadraj unutar zagrada izraunava prvi, to znai da e operator + biti izvren pre
operatora *.
Redosled po kome se izvravaju operatori prikazan je u tabeli dole - tamo gde su operatori
istog prioriteta (kao recimo * i /) redosled se odreuje sleva udesno:
Tabela 4.9. Prvenstvo operatora

Prvenstvo

Operator

Najvii

++, (korieni kao prefiksi); +, -(unarni)


*, /, %
+, =, *=, /=, %=, +=, -=
++, (korieni kao sufiksi)

Najnii

Zapamtite da se redosled moe promeniti upotrebom zagrada, kako je gore opisali

Imenovani prostori

Pre nego to nastavimo, bilo bi korisno da upoznamo imenovane prostore - metod .NET
okruenja kojim se obezbeuje kontejner koji sadri aplikacioni kod, i to tako da i kod i njegov
sadraj mogu biti jedinstveno identifikovani. Imenovani prostori se takoe koriste i pri
kategorisanju objekata .NET okruenja. Najvei deo tih objekata su definicije tipova, kao to
su recimo prosti tipovi (System. Int32 i slino).
C# kod se podrazumevano sadri u globalnim imenovanim prostorima. To znai da se tom
kodu moe pristupiti iz nekog drugog koda koji je unutar globalnih imenovanih prostora, tako
to se navede njegovo ime. Moemo koristiti i kljunu re namespace, da bismo
eksplicitno definisali imenovani prostor u bloku koda oivienom vitiastim zagradama. Takva
imena moraju biti kvalifikovana, ukoliko e ih koristiti kod izvan imenovanog prostora.
Kvalifikovano ime je ono koje sadri sve informacije o svojoj hijerarhiji. To znai da ukoliko
imamo kod u jednom imenovanom prostoru, koji treba da koristi ime definisano u nekom
drugom imenovanom prostoru, moramo ukljuiti referencu na ovaj imenovani prostor.
Kvalifikovana imena koriste znak(.) izmeu nivoa imenovanog prostora.
Na primer:
namespace LevelOne
{
//kod u imenovanom prostoru LevelOne
//ime "NameOne" definisano
}
//kod u globalnom imenovanom prostoru
Ovaj kod definie jedan imenovani prostor, LevelOne, kao i jedno ime u njemu, NameOne
(ovde nije upotrebljeno nita od pravog koda, da bi bilo uopteno; umesto toga stavljeni su
komentari tamo gde bi trebale da stoje definicije). Kod napisan unutar LevelOne imenovanog
prostora, poziva ovo ime upotrebom "NameOne" - nije potrebna nikakva druga klasifikacija,
Meutim, kod u globalnom imenovanom prostoru mora pozivati ovo ime na sledei nain:
"LevelOne.NameOne".
U okviru imenovanih prostora moemo definisati ugnedene imenovane prostore, takoe
koristei kljunu re namespace. Ugnedeni imenovani prostori se pozivaju preko svoje
hijerarhije, opet koristei taku da bi naveli svaki nivo unutar hijerarhije. Ovo emo
najbolje prikazati preko primera.

12

Razmotrite sledee imenovane prostore:


namespace LevelOne
{
//kod u imenovanom prostoru LevelOne
namespace LevelTwo
{
//kod u imenovanom prostoru LevelOne.LevelTwo
//ime "NameTwo" definisano
}
}
//kod u globalnom imenovanom prostoru
Ovde se NameTwo mora pozivati kao "LevelOne.LevelTwo.NameTwo" iz globalnog
imenovanog prostora; ili kao "LevelTwo.NameTwo" iz imenovanog prostora LevelOne; ili kao
"NameTwo" iz imenovanog prostora LevelOne.LevelTwo.
Vano je naglasiti da su imena jedinstveno definisana od strane njihovih imenovanih
prostora. Mogli bismo definisati ime "NameThree" u imenovanim prostorima LevelOne i
LevelTwo:
namespace LevelOne
{
//ime "NameThree" definisano
namespace LevelTwo
{
//ime "NameThree" definisano
}
}
Ovde smo definisali dva imena, LevelOne.NameThree i LevelOne.LevelTwo.NameThree,
koja se mogu koristiti nezavisno jedno od drugoga.
Kada definiemo imenovani prostor, moemo pojednostaviti pristup imenima koje sadre
pomou iskaza using. Iskaz using znai: U redu, trebae nam imena iz ovog imenovanog
prostora, pa se neemo muiti da svaki put navodimo njihova puna imena". Na primer, u
sledeem kodu kaemo da iz imenovanog prostora LevelOne treba da imamo pristup
imenima u imenovanom prostora LevelOne.LevelTwo bez klasifikacije:
namespace LevelOne
{
using LevelTwo;
namespace LevelTwo
{
//ime
"LevelTwo" definisano
}
}
Sada iz imenovanog prostora LevelOne moemo pozvati ime LevelTwo.NameTwo pomou
"NameTwo".

13

Ponekad, kao u primera NameThree, ovo moe dovesti do problema sa kolizijom istih imena u
razliitim imenovanim prostorima (kada se kod verovatno nee kompajlirati). U takvim
sluajevima, moemo definisati sinonim za imenovani prostor kao deo iskaza using:
namespace LevelOne
{
using LT=LevelTwo;
// ime "NameThree" definisano
namesp ace Lev elTwo
{

// ime "NameThree" definisano

}
}
Ovde se iz imenovanog prostora LevelOne ime LevelOne. NameThree poziva kao "NameThree", a
ime LevelOne.LevelTwo.NameThree kao "LT.NameThree". Iskaz using odnosi se na imenovani
prostor u kome se sadri, kao i na sve imenovane prostore ugnedene u njega. U gore navedenom
kodu globalni imenovani prostor ne moe koristiti "LT.NameThree". Meim, koristie iskaz using, na
sledei nain:
using LT = LevelOne.LevelTwo;
namespace LevelOne
{
//ime "NameThree" definisano

namespace LevelTwo
{
//ime "NameThree" definisano
}

Tada kod u globalnom imenovanom prostora kao i u LevelOne mogu koristiti


"LT.NameThree".
Ovde je vano podvui jo neto. Iskaz using sam po sebi ne daje vam pristup imenima u drugom
imenovanom prostoru. Ukoliko kod nije na neki nain povezan sa vaim projektom tako to je
definisan u izvornoj datoteci vaeg projekta, ili ukoliko nije deformisan unutar nekog drugog koda koji
je povezan sa vaim projektom, neemo imati pristup imenima koja sadri. Isto tako, ako je kod koji
sadri imenovani prostor povezan sa vaim projektom, pristup imenima koje sadri je omoguen, bez
obzira na to da li koristimo using. Iskaz using nam prosto olakava pristup ovim imenima, a moe i
prilino skratiti inae dugaak kod, da bi ga napravio razlonijim.
Ukoliko se vratimo na kod u Pozdrav Svete, sa poetka ovog predavanja, videemo sledee redove
koji se odnose na imenovane prostore:
using System;
namespace Pozdrav_Svete
{
.....
.....
}

Prvi red koristi using da definie imenovani prostor System koji e biti korien u ovom C# kodu, i
moe mu se pristupiti iz svih imenovanih prostora koji su u ovoj datoteci, bez klasifikacije. System
imenovani prostor je koreni imenovani prostor za aplikacije .NET okruenja i sadri sve osnovne
funkcionalnosti neophodne za konzolne aplikacije.
14

Zatim je deklarisan i imenovani prostor za samu aplikaciju, Pozdrav Svete.

Saetak
U ovom predavanju preli smo prilian deo terena koji se bavi pravljenjem korisnih (ako ne i
osnovnih) C# aplikacija. Upoznali smo se sa osnovama C# sintakse i analizirali osnove koda
konzolnih aplikacija koje VS generie za nas, kada se pravi konzolni aplikacioni projekat.
Najvei deo ovog predavanja, bavi se korienjem promenljivih. Videli smo ta su to
promenljive, kako se prave, kako im se dodeljuju vrednosti i kako se manipulie tim
vrednostima. Usput, upoznali smo se i sa osnovama interakcije sa korisnikom, tako to smo
videli kako ispisati tekst u konzolnoj aplikaciji i kako proitati ono to nam korisnik unese. Ovo
je ukljuilo samo osnovne tipove konverzije.
Takoe smo nauili kako formirati izraze pridruivanjem operatora i operanda, i kako se ovi
izvravaju i kojim redosledom.
Na kraju, upoznali smo se sa pojmom imenovanih prostora, koji e nam kako napredujemo
kroz knjigu postajati sve vaniji. Poto vam je ova tema predstavljena prilino skraeno,
stvorena je osnova za dalje diskusije.
Sve to smo do sada programirali izvrava se red po red.

Vebe
1. Kako pozvati ime veliki iz koda unutar imenovanog prostora cudan ?
namespace cudan
{
//kod u imenovanom prostoru cudan
}
namespace super
{
namespace velikani
{
// definisano ime veliki
}
}
2. Koje od navedenih imena promenljivih nije ispravno:
a)
b)
c)
d)
e)

mojaPromenljivaJeDobra
99Flake
_floor
time2GetJiggyWidIt
tf.zr.ac.yu

15

Kontrola toka programa


Sav kod u jeziku C# koji smo do sada videli ima neto zajedniko. U svakom od primera kod se
izvravao red po red, od gore ka dole, ne proputajui nita. Kada bi se svaka aplikacija
izvravala ovako, bili bismo vrlo ogranieni u onome to se da uraditi.
U ovom predavanju videemo dve metode kontrole toka programa, odnosno redosleda
izvrenja redova u C# kodu. Te dve metode su sledee:
Grananje - gde izvravamo kod uslovno, u zavisnosti od rezultata nekog poreenja, na
primer. Ovaj kod izvri samo ako je myVal manje od 10."
Petlje - ponavljanje izvrenja istih iskaza (odreeni broj puta, dok se ne dostigne uslov
koji je unapred zadat).
Obe tehnike ukljuuju korienje Bulove logike. U predavanju o prikazu tipova videli smo tip
bool, ali nismo mnogo radili sa njim. Krenuemo od toga ta se podrazumeva pod Bulovom
logikom, tako da bismo je mogli upotrebiti u toku kontrole programa.

Bulova logika

Tip bool, moe sadrati samo dve vrednosti: true ili false. Ovaj tip se esto koristi da bi se
zabeleio rezultat neke operacije, tako da moemo reagovati na osnovu tog rezultata.
Uglavnom se tipovi bool koriste da uskladite rezultat nekog poreenja.
Istorijski, vredelo bi seati se (i potovati) engleskog matematiara Dorda Bula, iji je rad sredinom
devetnaestog veka omoguio osnovu Bulove logike.

Kao primer, razmotrite situaciju u kojoj bismo eleli da izvrimo kod na osnovu toga da li je
promenljiva myVal manja od 10. Da bismo ovo uradili, moramo proveriti da li je iskaz myVal
je manje od 10" istinit ili neistinit. Tanije, moramo znati logiku vrednost rezultata tog
poreenja.
Logiko poreenje zahteva upotrebu logikog operatora poreenja (koji se jo zove i relacioni
operator), koji su prikazanih u donjoj tabeli. U svim ovim sluajevima, var1 je promenljiva
tipa bool, dok tipovi promenljivih var2 i var3 mogu biti razliiti.
Tabela 5.1. Operatori dodeljivanja

Operator

Kategorija

Primer izraza

==

binarni

var1=var2== var3;

!=

binarni

var1=var2!= var3;

<

binarni

var1=var2< var3;

>

binarni

var1=var2>var3;

<=

binarni

var1=var2<= var3;

>=

binarni

var1=var2>= var3;

Rezultat
var1 je dodeljena vrednost true ako je
var2 jednaka var3, u suprotnom false.
var1 je dodeljena vrednost true ako je
var2 nije jednaka var3, u suprotnom false.
var1 je dodeljena vrednost true ako je
var2 manja od var3, u suprotnom false.
var1 je dodeljena vrednost true ako je
var2 vea od var3, u suprotnom false.
var1 je dodeljena vrednost true ako je
var2 manja ili jednaka var3, u suprotnom
false.
var1 je dodeljena vrednost true ako je
var2 vea ili jednaka var3, u suprotnom
false.

Moemo koristiti ove operatore na brojnim vrednostima u kodu kao to je:


bool isLessThan1O;
isLessThan1O = myVal < 10;

...

U ovom kodu bie dodeljena vrednost true promenljivoj isLessThan1O, ako je vrednost
promenljive myVal manja od 10, u suprotnom bie dodeljena vrednost false. Ove operatore
poreenja moemo koristiti i na drugim tipovima, kao to su stringovi:
bool isPetar;
isPetar =myString == "Petar";

Ovde e isPetar biti istinita samo ako myString u sebi ima string "Petar". Takoe se moemo
fokusirati i na logike vrednosti:
bool isTrue;
isTrue = myBool == true;

Ipak, ovde smo ogranieni na korienje samo operatora == i ! =.


Upamtite da e doi do greke u kodu ako sluajno pretpostavite da va11>va12 mora biti true zato to je
va11<va12 false. Ako je va11 == va12 onda su oba ova iskaza false.

Postoje i drugi logiki operatori koji su namenjeni iskljuivo radu sa logikim vrednostima:
Tabela 5.2. Operatori dodeljivanja

Operator

Kategorija

Primer izraza

unarni

var1=!var2;

&

binarni

var1=var2& var3;

binarni

var1=var21 var3;

binarni

var1=var2 var3;

Rezultat
var 1 je dodeljena vrednost true ako je
var2 false, ili vrednost false ako je var2
true (logiko NE).
var1 je dodeljena vrednost true ako var2 i
var3 imaju vrednost true u suprotnom
false (logiko I).
var1 je dodeljena vrednost true ako var2
ima vrednost true ili var3 ima vrednost
true ili obe promenljive imaju vrednost
true, u suprotnom dobija vrednost false
(logiko ILI).
var1 je dodeljena vrednost true ako var2
ima vrednost true ili var3 ima vrednost
true, ali ne i ako obe promenljive imaju
vrednost true, u suprotnom false (Logiko
ekskluzivno ILI).

Tako poslednji primer koda moe biti napisan i kao:


bool isTrue;
isTrue = myBool & true;

Operatori & i I imaju dva slina operatora:


Tabela 5.3. Operatori dodeljivanja

Operator

Kategorija

Primer izraza

&&

binarni

var1=var2&&var3;

||

binarni

var1=var2||var3;

Rezultat
var1 je dodeljena vrednost true ako var2 i
var3 imaju vrednost true, u suprotnom
false (logiko I)
var1 je dodeljena vrednost true ako var2
ili var3 (ili obe promenljive) imaju
vrednost true, u suprotnom var1 dobija
vrednost false (logiko ILI)

Njihov rezultat je potpuno isti kao & i |, ali postoji bitna razlika u nainu na koji se dobija njihov
rezultat, to moe dati bolje performanse programa. Oba operatora prvo ispituju vrednost prvog
operanda (var2 u tabeli gore), pa na osnovu vrednosti ovog operanda moda nee biti potrebno
da se ispita drugi operand (var 3 gore).
Ako je vrednost prvog operanda operatora && false, onda nema potrebe ispitivati vrednost
drugog, zato to e rezultat, bez obzira na drugi operand biti false. Slino tome operator | |
vratie vrednost true, ako je prvi operand true, bez obzira na vrednost drugog operanda.
Ovo nije sluaj sa operatorima & i | koje smo videli pre toga. Kod njih e oba operanda uvek biti
izraunata.
Zbog ovog uslovnog izraunavanja operanada, primetiemo malo poboljanje performansi ako
koristimo operatore & & i | | umesto & i |. Ovo e biti posebno oigledno u aplikacijama u
kojima se esto upotrebljavaju ovi operatori. Neko opte pravilo je da uvek treba koristiti
operatore & & i I I gde god je to mogue.

Iskaz

goto

Jezik C# dozvoljava da se odreeni delovi koda obelee i da se na ta mesta direktno skae


pomoi j iskaza goto, to nam koristi, ali i stvara probleme. Glavna korist je u tome to moemo
na jednostavan nain kontrolisati ta se u kodu izvrava i kada. Glavni problem lei u preteranoj
upotrebi, jer se na taj nain stvara nerazumljiv pageti kod.
Pogledajmo kako da potvrdimo ovo to smo naveli Iskaz goto se koristi na sledei nain:
goto <imeOznake>;
Oznake se definiu na sledei nain:
<imeOznake>:
Na primer razmotrimo sledee:
int myInteger = 5;
goto myLabel;
myInteger +=10;
myLabel:
Console.WriteLine("myInteger = {0}", myInteger);

Program se izvrava na sledei nain:


Promenljiva mylnteger je deklarisana kao tip int i dodeljena joj je vrednost 5
Iskaz goto prekida normalan tok programa i prebacuje kontrolu na red obeleen sa myLabel:
Vrednost mylnteger se ispisuje na konzoli.
Naznaeni deo koda ispod, nikada se ne izvrava:
int myInteger = 5;
goto myLabel;
myInteger += 10;
myLabel:
Console.WriteLine("myInteger = {0}", myInteger);
Ako isprobate ovo u nekoj aplikaciji, videete da je, kad pokuate da kompajlirate, u listi
zadataka navedeno upozorenje "Unrechable code detected", zajedno sa brojem reda.
Iskazi goto imaju svoju upotrebu, ali mogu prilino zakomplikovati stvari. Kao primer pageti
koda proisteklog iz iskaza goto, pogledajte sledee:
start:
int myInteger = 5;
goto addVal;
writeResult:
Console. WriteLine ("myInteger = (0)", myInteger);
goto start;
addVal:
myInteger +=10;
goto writeResult;
Ovaj kod je potpuno ispravan, ali je neitljiv! Ako elite da ovo sami isprobate, pokuajte da
vidite ta ovaj kod radi samo gledanjem u njega.
Vratiemo se ovom iskazu i svim njegovim implikacijama malo kasnije.

Grananje

Grananje je in kontrole toga koji red koda treba da se izvri sledei. Red na koji se skae zavisi
od neke vrste uslovnog iskaza. Taj uslovni iskaz bie zasnovan na poreenju izmeu test
vrednosti i jedne ili vise moguih vrednosti sa korienjem Bulove logike.
U ovom delu pogledaemo tri tehnike grananja dozvoljenih u jeziku C#:
ternarni operator
iskaz if
iskaz switch

Ternarni operator
Najjednostavniji nain da se izvede poreenje jeste pomou ternarnog (ili uslovnog) operator!.
Ve smo videli unarne operatore koji rade sa jednim operandom kao i binarne koji rade sa dva
operanda, tako da ne udi to ternarni koristi tri operanda. Sintaksa je sledea:
<test> ? <resultIfTrue> : <resultIfFalse>
Ovde se ispituje <test> da bi se dobila logika vrednost, pa je rezultat operator
<resultIfTrue> ili <resultIfFalse> u zavisnosti od te vrednosti.
Ovo moemo koristiti u sledeem:
string resultString = (myInteger < 10)

? "Manje od 10"
: Vee ili jednako 10";

Ovde je rezultat ternarnog operatora jedan od dva stringa, od kojih oba mogu biti dodeljeni
promenljivoj resultString. Izbor se vri na osnovu poreenja vrednosti promenljivi myInteger sa
10, pa ukoliko je myInteger manje od 10, prvi string se smeta i resultString, a ukoliko je vee
ili jednako 10, resultString se upisuje u drugi string. Na primer, ako je myInteger 4, onda je
resultString string "Manje od 10".
Ovaj operator je dobar za male zadatke nalik ovom, ali nije odgovarajui za velike koliine kodi
bazirane na poreenju. Mnogo bolji nain da se to uradi jeste pomou iskaza if.

Iskaz if
Iskaz if je mnogo bolji i raznovrsniji nain za donoenje odluka. Za razliku od iskaza ?:, iskaz iff
nema rezultat (pa ga zato ne koristimo prilikom dodele); umesto toga, ovaj iskaz koristimo dii
uslovno izvrimo druge iskaze.
Najjednostavnije korienje iskaza if je sledee:
If (<test>):
<kod se izvrava ako je test istinit >;
Ovde se <test> izraunava (mora biti logika vrednost da bi se kod kompajlirao), a iskaz ispod se
izvrava ako uslov <test> ima vrednost true. Nakon izvrenja tog koda, ili ukoliko <test> imao
rezultat false, program se nastavlja od sledeeg reda koda.
Moemo navesti i dodatni kod koristei iskaz else u kombinaciji sa iskazom if. Ovaj iskaz se
izvrava ako <test> ima vrednost false:
if (<test>)
<kod se izvrava ako je <test> true>;
else
<kod se izvrava ako je <test> false>;

Oba dela ovog koda mogu se prostirati u vie redova ogranienih vitiastim zagradama:
if (<test>)
{
<kod se izvrava ako je <test> true>;
}
else
{
<kod se izvrava ako je <test> false>;
}
Kao kratak primer, prepravimo kod u kome smo koristili ternarni operator:
string resultString = (myInteger < 10) ? "Manje od 10" :
"Vee ili jednako 10";
Poto rezultat iskaza if ne moemo dodeliti promenljivoj, vrednost promenljivoj se mora dodeliti
u posebnom koraku:
string resultString;
if (mylnteger < 10)
resultString = "Manje od 10"
else
resultString = "Vee ili jednako 10";
Kod kao ovaj, iako je sloeniji, mnogo je laki za itanje i razumljiviji je od ekvivalentnog u
ternarnom obliku, a dozvoljava i veu fleksibilnost.
Uradimo vebu.

Veba br. 4.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location:
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba4 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: IskazIf
Dodajte sledei kod u Class1.cs:

Pokrenite program i unesite dva broja kad zatrai:

Kako to radi
Prvi deo koda vam je poznat i on obezbeuje unos vrednosti tipa double od korisnika:

Zatim dodeljujemo string promenljivoj komparacija tipa string, na osnovu vrednosti koje
sadre promenljive prom1 i prom2. Prvo proveravamo da li je prom1 manje od prom2:

Ukoliko to nije sluaj, prom1 je ili vee ili jednako prom2. Unutar dela else prvog poreenja
moramo da ugnezdimo drugo poreenje.:

Do else dela drugog poreenja doi e se samo ako je prom1 vee od prom2:

I na kraju ispisujemo vrednost poreenja na konzolu:

Ugnjedavanje koje smo koristili jeste samo jedan od naina. Isto tako smo mogli da
napiemo da ispitijumo svaki put promenljive
Manjkavost ove metode jeste u tome to se izvode tri poreenja, bez obzira na vrednosti
prom1 i prom2. Prvom metodom izvodimo samo jedno poreenje ako prom1<prom2 ima
vrednost true i dva poreenja u suprotnom (takoe izvodimo poreenje prom1 == prom2), to
zajedno ini manji broj redova koje se izvravaju. Ovde e razlike u performansama biti
minimalne, ali to nee biti sluaj i u aplikacijama kojima je jako bitna brzina izvravanja.

Proveravanje uslova korienjem iskaza if

U prethodnom primeru proveravali smo tri uslova koji ukljuuju vrednost prom1. Ovo je
pokrilo sve mogue vrednosti promenljive. U drugim sluajevima moda emo eleti da
proverimo specifine vrednosti, recimo ako je prom1 jednako 1, 2, 3 ili 4, ili slino. Ako
koristimo kod nalik onome od malopre, to moe prouzrokovati vrlo neprijatno ugneden kod,
na primer:
if (prom1 == 1)
{
// uradi neto
}
else
{
if (prom1 == 2)
{
// uradi neto drugo
}
else
{
if (prom == 3)
{
// uradi neto drugo
}
else
{
// uradi neto drugo
}
}
}

Upamtite da je esta greka pisati kod kao to je trei uslov u obliku if (prom1 ==3 || == 4). Ovde, redosledu
izvrenja, operator == se izvrava prvi, ostavljajui operatoru | | da radi sa logikim i numerikim operandom. Ovo e
prouzrokovati greku.

U ovakvim situacijama vredi koristiti malo izmenjenu emu uvlaenja teksta i spajanje bloka
koda za else blokove (odnosno jednog reda posle else bloka koda, umesto novog bloka). Kada
se ovo uradi, dobije se struktura koja ukljuuje else if iskaz:
if (prom1 == 1)
{
// uradi neto
}

Iskaz else if predstavlja u stvari, dva odvojena iskaza, dok je kod funkcionalno identian
onome pre njega. Pa ipak, ovaj kod je mnogo laki za itanje.
Kada pravite viestruka poreenja kao to je ovo, vredi razmisliti o iskazu switch kao
alternativnoj strukturi grananja.

Iskaz switch
Iskaz switch je vrlo slian iskazu if po nainu uslovnog izvravanja koda na osnovu neke
vrednosti dobijene iz testa. Meutim, switch nam dozvoljava da ispitamo vise razliitih
vrednosti test promenljive odjednom, umesto samo jednog uslova. Ovaj test je ogranien na
diskretne vrednosti, umesto na lanove kao to je " vee od X", pa je i njegova upotreba malo
drugaija, ali i dalje moe biti mona tehnika.
Osnovna struktura switch iskaza je sledea:
switch (<testProm>)
{
case <constIzraz11>:
<kod koji se izvrava ako je <testProm> == <constIzraz11> >
break;
case <constIzraz12>:
<kod koji se izvrava ako je <testProm> == <constIzraz12> >
break;
....
....
case <constIzraz1N>:
<kod koji se izvrava ako je <testProm> == <constIzraz1N> >
break;
default::
<kod koji se izvrava ako je <testProm> != <constIzrazi> >
break;
}

Vrednost u promenljivoj <testProm> poredi se sa svakom od vrednosti <constIzrazX>


(navedenim u iskazu case) i ako postoji poklapanje, onda se izvrava kod predvien za to.
Ukoliko ne postoji poklapanje ni sa jednom vrednou, onda se izvrava kod u delu default,
ako takav blok postoji. Na kraju koda svake sekcije imamo dodatnu komandu break.
Nelegalno je za tok izvrenja programa da prede u sledei case iskaz, ako se obradio case
blok pre njega.
Upamtite da se ova oblast u jeziku C#, razlikuje od jezika C++ gde je dozvoljeno izvrenje
jednog case iskaza iza drugog.
Iskaz break ovde jednostavno obustavlja iskaz switch i prelazi na sledei iskaz prate strukturu
programa.
U okviru jezika C# postoje alternativne metode spreavanja toka izvrenja jednog case iskaza
iza drugog. Moemo koristiti iskaz return, koji obustavlja izvrenje trenutne funkcije a ne
samo switch strukture, ili goto iskaz. Iskaz goto (kao to je ranije navedeno) ovde radi, zato
to iskaz case u stvari definie oznake u C# kodu. Na primer:
switch (<testProm>)
{
case <constIzraz11>:
<kod koji se izvrava ako je <testProm> == <constIzraz11> >
break;
goto case <constIzraz12>:
<constIzraz12>:
<kod koji se izvrava ako je <testProm> == <constIzraz12> >
break;
....
....

Ovde postoji izuzetak od pravila da izvravanje jednog case iskaza ne moe slobodno da
prede u sledei. Ako postavimo vise case iskaza zajedno pre jednog bloka koda, mi u stvari
proveravamo viestruke uslove odmah. Ako je bilo koji od uslova ispunjen, kod se izvrava.

Na primer:
switch (<testProm>)
{
case <constIzraz11>:
case <constIzraz12>:
<kod koji se izvrava ako je <testProm> == <constIzraz11> > ili
<testProm> == <constIzraz12> >
break;
....
....

Upamtite da se ovi uslovi odnose takoe i na iskaz default. Ne postoji nikakvo pravilo po
kome ovaj iskaz mora biti zadnji u listi poreenja, pa ga moemo postaviti u grupu sa
iskazima case, ako to elimo. Dodavanje take prekida pomou break, goto ili return
osigurava pravilno izvrenje putanje kroz strukturu u svim iskazima case.
Svaki od poreenja <constIzrazX> mora biti konstantna vrednost. Jedan od naina da se ovo
postigne jeste da obezbedimo vrednost literala, na primer:
switch (<mojInteger>)
{
case 1:
<kod koji se izvrava ako je mojInteger == 1> >
break;
case -1:
<kod koji se izvrava ako je mojInteger == -1> >
break;
default :
<kod koji se izvrava ako je mojInteger != poreenja>
break;
}

Jo jedan od naina jeste i da koristite konstantne promenljive. Konstantna promenljiva je


nalik bilo kojoj drugoj promenljivoj, osim to se razlikuje u kljunoj stvari - vrednost koju
sadri nikad se ne menja. Jednom kad dodelimo vrednost konstantnoj promenljivoj, ta
vrednost ostaje do kraja izvrenja programa. Konstantne promenljive nam u ovom sluaju
pomau, zato to je esto lake itati kod gde su prave vrednosti koje se uporeuju skrivene
od nas u vreme poreenja.
Konstantne promenljive se deklariu korienjem kljune rei const, kao dodatak tipu
promenljive i pri torn im moraju biti dodeljene vrednosti, na primer:
const int intTwo = 2;
Ovaj kod je potpuno ispravan, ali ako pokuamo:
const int intTwo;
intTwo = 2;
pojavie se greka pri kompajliranju. Ovo e se dogoditi i ako pokuamo da promenimo
vrednost I konstantne promenljive, na bilo koji nain posle prve dodele vrednosti.
Pogledajmo primer iskaza switch koji koristi konstantne promenljive.

10

Veba br. 5.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).U okviru za tekst Location,promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba5
(ovaj e direktorijum biti automatski napravljen ukoliko ve ne postoji), i ostavite
podrazumevani tekst u okviru za tekst Name: IskazSwitch.
Dodajte sledei kod u Class1.cs:

Pokrenite program i unesite ime:

Kako to radi
Na kod postavlja tri konstante tipa string, prihvata promenljivu tipa string od korisnika, a
zatim ispisuje tekst na konzolu, zasnovan na tome ta je uneto. U ovom sluaju promenljive
tipa string su imena.
Kada uporedimo uneseno ime (u promenljivoj ime) sa konstantnom vrednou, prvo ga
prebacujemo u mala slova pomou metoda ime.ToLower() . To je standardna komanda koja
e raditi sa svim promenljivama tipa string i priskae nam u pomo kada nismo sigurni ta je
korisnik uneo. Koriste ovu tehniku stringovi "Petar", "peTAR", "petar" itd., poklopi e se sa
test stringom "petar".
11

Iskaz switch sam po sebi pokuava da pronae poklapanje unetog stringa sa konstantnom
vrednou koja je definisana i ispisuje linu poruku da, ako uspe, pozdravi korisnika. Ako ne
pronaemo poklapanje, samo pozdravljamo korisnika.
Iskaz switch nema ogranienja na broj iskaza case koje sadri, tako da moete proiriti ovaj
kod za svako ime koje vam padne na pamet, ako elite, samo to e potrajati.

Petlje

Petlje predstavljaju ponavljanje izvrenja iskaza. Ova tehnika moe biti od velike pomoi,
jer omoguava ponavljanje operacije koliko god hoemo puta (na hiljade, ili ak milione
puta), bez potrebe da svaki put piemo istu.
Kao primer, razmotrimo sledei kod za izraunavanje koliine novca na bankovnom raunu
posle deset godina, pretpostavljajui da je kamata plaena svake godine i da nema drugih
priliva ili odliva sa rauna:
double balance = 1000;
double interestRate = 1,05; // 5% kamate godinje
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;
balance *= interestRate;

Pisanje istog koda 10 puta deluje kao razbacivanje vremena, a i ta ako moramo da
promenimo sa 10 na neki drugi broj godina ? Morali bismo da runo iskopiramo red po red
traeni broj puta, to bi bilo naporno.
Umesto toga moemo da koristimo petlju koja izvrava instrukcije koje mi elimo odreen
broj puta.
Jo jedan vaan tip petlji jeste onaj gde ostajemo u petlji dok se neki uslov ne ispuni. Ove
petlje su malo jednostavnije (lako nita manje korisne), pa emo poeti sa njima.

Petlje do
Petlje do rade na sledei nain: kod koji je obeleen unutar petlje se izvrava; zatim se
izvodi logiki test; pa se kod izvrava ponovo ako je rezultat tog testa true i tako dalje. Iz
petlje se izlazi kada rezultat testa postane false.
Struktura do petlje izgledao ovako:
do
{
}

<kod koji se ponavlja u petlji>


while (<test>);

gde je <test> logika vrednost.

12

Taka-zarez posle while iskaza je neophodna. Uobiajena greka je da se ona zaboravi.


Ovo moemo koristiti da bismo recimo, napisali brojeve od 1 do 10 u koloni:
int i=1;
do
{
Cosole.WriteLine({0}, i++);
} while (i<=10);

Ovde koristimo sufiks verziju operatora ++ da bismo poveali vrednost promenljive i poto se
ispie na ekranu, tako da moramo proveriti da li je i<=10, da bismo ukljuili i 10 u brojeve
koji se ispisuju na konzolu.
Iskoristimo ovo da malo modifikujemo kod koji smo u uvodu ovog dela knjige koristili da
Izraunamo stanje na raunu posle 10 godina. Ovde emo koristiti petlju da bismo izraunali
koliko je godina potrebno da doemo do odreene sume novca, na osnovu poetne sume i
kamatne stope.

Veba br. 6.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).U okviru za tekst Location,promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba6
(ovaj e direktorijum biti automatski napravljen ukoliko ve ne postoji), i ostavite
podrazumevani tekst u okviru za tekst Name: IskazDo.
Dodajte sledei kod u Class1.cs:

13

3. Pokrenite aplikaciju i unesite neke vrednosti:

Kako to radi
Ovaj kod prosto ponavlja jednostavnu godinju kalkulaciju stanja, sa fiksnom kamatnom
stopom, onoliko puta koliko je potrebno da bi se zadovoljio zadati uslov koji okonava petlju.
Brojimo koliko godina je potrebno da se izraunava kamata, tako to poveavamo brojaku
promenljivu za svaki novi ciklus u petlji:

Ovu broja promenljivu moemo zatim koristiti u izlaznom rezultatu:

Upamtite daje ovo moda najea upotreba ternarnog operatora?: da bise uslovno
formatirao tekst sa minimumom koda. Ovde stavljamo a posle godin ako brojGodina nije
jednaka 1.
Na alost, ovaj kod nije savren. Razmotrite situaciju u kojoj je traeno stanje manje od
trenutnog stanja. U ovom sluaju izlazni podaci e biti:

do petlje uvek izvravaju bar jedan ciklus. Ponekad, kao u ovoj situaciji, to nije idealno.
Naravno, moemo dodati iskaz if:

14

Ali ovo izgleda kao da bespotrebno komplikujemo kod. Mnogo bolje reenje je koristiti petlju
while.

Petlje while
Petlje while su dosta sline do petljama sa jednom bitnom razlikom: logiki test se u
petljama while izvrava na poetku, a ne na kraju ciklusa. Ukoliko je rezultat testa false,
ciklus petlje se nikad ne izvri. Umesto toga izvrenje programa odmah skae na red koda
koji se nalazi iza petlje.
Petlje while se definiu na sledei nain:
while (<test>)
{
<kod unutar petlje>
}
Mogu se koristiti skoro na isti nain kao i petlja do, na primer:
int i=1;
while (i<=10)
{
Console.WriteLine(" (0)", i++);
}
Ovaj kod nam daje isti rezultat kao do petlja koju smo ranije videli - ispisuje brojeve od 1 do
10 u koloni. Izmenimo poslednji primer tako da iskoristimo petlju while.

15

Veba br. 7.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).U okviru za tekst Location,promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba7
(ovaj e direktorijum biti automatski napravljen ukoliko ve ne postoji), i ostavite
podrazumevani tekst u okviru za tekst Name: IskazWhile.
Dodajte sledei kod u Class1.cs:
Prepravite kod na sledei nain tako to iskoristite kod iz prethodnog primera, samo obriite
iskaz while na kraju originalne petlje.

Pokrenite ponovo aplikaciju, ali ovaj put unesite traenu vrednost


nost stanja koja je manja od
poetnog stanja:

Kako to radi
Ova jednostavna promena iz petlje do u petlju while, reava problem u zadnjem primeru.
Tako to smo premestili logiki test sa kraja petlje na poetak, obezbedili smo se za situacije
16

kada nije potrebno izvravati petlju, tako da moemo odmah skoiti na rezultat.
Postoje naravno i alternative za ovakvu situaciju. Na primer, moemo proveriti korisnikov
unos da bismo se osigurali da je traeno stanje vee od poetnog stanja.
U ovakvim situacijama moemo postaviti unos korisnika u petlju na sledei nain:

Ovo e odbaciti vrednosti koje nemaju smisla, tako da emo dobiti sledee:

Ispravnost korisnikovog unosa je vana tema kada doe do dizajna aplikacije.

17

Petlje for
Poslednja vrsta petlji koju emo videti u ovom predavanju jeste petlja for, koja se izvrava
unapred odreeni broj puta i odrava svoj sopstveni broja. Da bi se definisala for petlja,
trebaju nam sledee informacije:
Poetna vrednost za inicijalizaciju brojake promenljive;
Uslov za nastavak petlje, koji ukljuuje brojaku promenljivu;
Operacija koja se izvrava nad brojakom promenljivom na kraju svakog ciklusa petlje.
Na primer, ako elimo petlju sa brojaem koji se poveava od 1 do 10 u koracima po jedan,
poetna vrednost je 1 - uslov je da broja bude manji ili jednak 10, a operacija koja se izvodi
na kraju svakog ciklusa je poveavanje brojaa za jedan.
Ove informacije moraju biti smetene u strukturu for petlje na sledei nain:
for (<inicijalizacija>; <uslov>, <operacija>)
{
<kod unutar petlje>
}

Ovo radi na isti nain kao sledea petlja while:


(<inicijalizacija>
while (<uslov>)
{
<kod unutar petlje>
<operacija>
}

Meutim, format petlje for ini k6d itljivijim, zato to sintaksa ukljuuje specifikaciju
kompletne petlje na jednom mestu, umesto da je podeljena na vise razliitih iskaza u
razliitim delovima koda.
Ranije smo koristili petlje while i do da bismo ispisivali brojeve od 1 do 10. Pogledajmo kakav
kod je potreban da bi se to izvelo sa petljom for:
int i;
for (i=1; i<=10; ++ i)
{
Console.Writeline({0}, i);
}

Brojaka promenljiva je celobrojna vrednost sa imenom i, poetne vrednosti 1, i poveava se


za 1 na kraju svakog ciklusa. Tokom svakog ciklusa vrednost i se ispisuje na konzoli.
Primetiete da se kod zaustavlja kada i dostigne vrednost 11. To je zato to se na kraju
ciklusa u kome je i jednako 10 , i povea na 11. To se dogaa pre obrade uslova i<=10 kada se
petlja i zavrava.
Kao i kod petlji while, i petlje for se izvravaju samo kada je vrednost uslova true pre prvog
ciklusa, tako da kod u petlji ne mora ni da se izvri.
Konano, moemo deklarisati brojaku promenljivu kao deo for iskaza, tako to emo
prepravi" kod od malopre:
for (int i=1; i<=10; ++ i)
{
Console.Writeline({0}, i);
}

18

Mada, ako ovo uradimo, promenljiva i nee biti dostupna izvan ove petlje. Pogledajmo primer
korienja petlji for. Poto smo do sada prilino koristili petlje, uiniu ovaj primer malo
interesantnijim: prikazae Mandelbrotov skup (koristei obine tekstualne znakove, tako da
nee izgledati spektakularno!).

Veba br. 8.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).U okviru za tekst Location,promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba8
(ovaj e direktorijum biti automatski napravljen ukoliko ve ne postoji), i ostavite
podrazumevani tekst u okviru za tekst Name: IskazFor.
Dodajte sledei kod u Class1.cs:

Korienje petlji for


1.
Napravite novu konzolnu aplikaciju u direktorijumu C: \BegCSharp\Chapter4 l nazovite jeChO4ExO6.
2. Dodajte sledei kod u Classl.
cs:
static void Main (string [] args) {
..,
double realCoor, imagCoord; -" '- ' ; -,,'
double realTemp, imagTemp, realTemp2, arg;
int iterations;
for (imagCoord = 1.2; imagCoord >= -1.2; imagCoord -= 0.05)
for (realCoord = -0.6; realCoord <= 1.77; realCoord += 0.03)
iterations =0;
:
realTerap = realCoord;
imagTemp = imagCoord;
arg = (realCoord * realCoord) + (imagCoord * imagCoord);
while {(arg < 4) && (iterations < 40))
( ,.. '
'' .'.
: J....-..,.;;-.*-,,...-,
. realTemP2 = (realTemp * realTemp) - (imagTemp * imagTemp)
19

Pokrenite kod

Kako to radi
Neemo ulaziti u detalje kako se radi izraunavanje Mandelbrotovog skupa, ali demo preci
osnove, da bismo shvatili zato nam trebaju petlje koje smo koristili. Slobodno preskoite
sledea dva paragrafa, ako vas ne interesuje matematika - bitno je shvatiti kako se ponaa
kod.
Svaka pozicija u Mandelbrotovoj slici odgovara imaginarnom broju oblika N=x+y*i, kome je
realni deo x, imaginarni deo y, a i je kvadratni koren iz -1. Koordinate x i y na slid
odgovaraju x i y delu imaginarnog broja.
Za svaku poziciju na slici posmatramo argument N, to je kvadratni koren iz x*x + y*y. Ako je
ova vrednost vea ili jednaka 2, onda za ovu poziciju kaemo da ima vrednost 0. Ako je N
manje od 2 onda menjamo N u vrednost N*N-N (to nam daje N= (x*x-y*y* -x) + (2*x*y-y) *i).
Opet proveravamo vrednost argumenta N, ako je ova vrednost vea ili jednaka 2 za nju
kaemo da pozicija ovog broja odgovara vrednosti 1. Ovaj proces se nastavlja sve dok ne
dodelimo vrednost poziciji na slici ili dok se ne izvri odreeni broj iteracija.
Na osnovu vrednosti dodeljene svakoj taki na slici, imali bismo, u grafikom okruenju,
mesto za taku odreene boje na ekranu. Meutim, poto koristimo tekstualno okruenje , mi
samo postavljamo znak na ekran.
Pogledajmo kod i koje petlje on sadri. Poeemo od deklarisanja promenljivih koje e nam
trebati za proraun:
double realKoord, imagKoord;
double realPom, imagPom, realPom2, arg;
int iteracija;

20

Ovde su realKoord i imagKoord realni i imaginarni delovi N, dok e druge promenljive tipa
double sluiti za uvanje privremenih informacija za vreme izraunavanja. Promenljiva
iteracija pamti koliko nam iteracija treba da bi argument N(arg) bio 2 ili vei
Zatim pokreemo dve for petlje, da bismo proli kroz koordinate pokrivaju i celu sliku
(koristimo malo kompleksniju sintaksu za promenu brojaa u odnosu na ++ ili , uobiajenu i
monu tehniku):

Izabrali smo odgovarajua ogranienja da bismo prikazali glavni deo Mandelbrotovog skupa.
Slobodno se igrajte sa ovim ako elite da isprobate zumiranje slike.
U okviru ove dve petlje imamo k6d koji se dri odreene take u Mandelbrotovom skupu,
dajui j nam vrednost za N da se pozabavimo. Ovde iterativno vrimo traeni proraun, koji
nam daje j vrednost koju ispisujemo za tekuu taku.
Prvo inicijalizujemo odreene promenljive:

Sledea je petlja while koja izvodi nau iteraciju. Ovde koristimo petlju while umesto petlje
do, za sluaj da je argument poetne vrednosti N vei od 2, u kom sluaju je iteracija=0 , pa
dalja izraunavanja nisu potrebna.
Upamtite da se ovde argument ne izraunava do kraja, ve samo vrednost x*x +y*y koja se
proverava da bi se videlo da li je vrednost manja od 4. Ovo pojednostavljuje raunanje,
poto znamo da je 2 kvadratni koren iz 4 i nema potrebe da sami izraunavamo kvadratne
korene:

Maksimalni broj iteracija ove petlje, koji izraunava vrednosti kako je gore navedeno, je 40.
Kada dobijemo vrednosti za trenutnu taku smetenu u iteracija, koristimo iskaz switch da
izaberemo znak za izlaz. Ovde koristimo samo 4 razliita znaka, umesto 40 moguih
vrednosti, i koristimo operator modula (%) tako da vrednosti 0,4, 8 i tako dalje daju jedan
znak, vrednosti 1, 5,9 i tako dalje daju drugi znak i slino:

21

Upamtite da koristimo metod Console.Write() umesto Console.WriteLine(), poto ne elimo


novi red svaki put kada se ispisuje znak.
Na kraju jedne od najvie uvuenih for petlji elimo da zavrimo red, tako da koristimo
iskonu sekvencu koju smo ranije upoznali kako bismo na izlaz poslali znak za novi red:
Console.Write("\n");
Rezultat ovoga je da se svaki red odvaja od sledeeg i poravnava u liniju na pravi nain.
Konani rezultat ove aplikacije, iako nije spektakularan, dovoljno je impresivan i prilino
lepo prikazuje od kakve koristi nam mogu biti petlje i grananja.

Prekidanje petlji
S vremena na vreme zatreba nam finija kontrola nad kodom koji se izvrava u petlji. Jezik C#
obezbeuje etiri komande koje nam pomau u tome. Tri od njih smo ve videli u dragim
situacijama:
break-trenutno zavrava petlju
continue - trenutno zaustavlja ciklus petlje (izvravanje se nastavlja od sledeeg ciklusa)
goto - dozvoljava iskakanje iz petlje na obeleeno mesto u kodu (nije preporuljivo ako
elite da vam kod bude itljiv)
return - iskae iz petlje i iz funkcije koja je sadri.
Komanda break jednostavno izlazi iz petlje i nastavlja izvrenje prvog reda koda posle
petlje, na primer:
int i = 1;
while (i <=10);
{
if (i ==6)
break;
Console.WriteLine({0}, i++);
}

Kod e ispisati brojeve od 1 do 5, poto e komanda break prouzrokovati izlaz kada i bude
jednako 5.

22

continue zaustavlja samo trenutni ciklus, a ne celu petlju, na primer:


int i = 1;
for (i=l; i<=10; i++) ;
{
if ( (i. % 2)==0)
continue;
Console.WriteLine(i) ;
}

Trei metod je korienje iskaza goto kao to smo videli ranije, na primer:
int i = 1;
while (i <=10) ;
{
if (i == 6)
goto TackaIzlaza;
Console.WriteLine (" (0) ", i++) ;
}
Console.WriteLine ("Ovaj kod se nikad nee izvriti . ");
TackaIzlaza:
Console.WriteLine ("Ovaj kod se izvrava kad se iz petlje izae uz pomo goto. ");

Upamtite da je izlazak iz petlje sa goto dozvoljen (iako je to neuredno), ali nije dozvoljeno
uskakanje u petlju spolja.

Beskonane petlje
Mogue je (grekom ili namerno), definisati petlje koje se nikada ne zavravaju, takozvane
beskonane petlje. Kao vrlo jednostavan primer pogledajte sledee:
while (true)
{
// kod u petlji
}

Ova situacija moe biti korisna ponekad, a iz takvih petlji uvek moemo izai pomou iskaza
break.
Meutim, kada se ovo dogodi sluajno, moe biti vrlo neprijatno. Pogledajte sledeu petlju
koja je slina for petlji u zadnjem delu:
int i = 1;
while (i <=10);
{
if ((i % 2)==0)
continue;
Console.WriteLine{"{0}", i++);
}

Ovde se i ne poveava sve dok ne doe do zadnjeg reda u petlji, koja se nalazi posle continue
iskaza. Ako se doe do continue iskaza (to se dogaa ako je i jednako 2) sledei ciklus e
koristiti istu vrednost za i, nastavljajui petlju, ispitujui istu vrednost i, i tako dalje. Ovo e
prouzrokovati zamrzavanje aplikacije. Upamtite da je i iz takvih aplikacija mogue izai na
normalan nain, tako da nema potrebe da resetujete raunar ako se to dogodi.

23

Saetak

U ovom predavanju, proirili smo nae programersko umee, koristei razliite strukture koje
moemo primeniti u naem kodu. Pravilna upotreba ovih struktura je od velikog znaaja kada
ponemo da pravimo kompleksnije aplikacije, a vremenom emo ih videti u ovoj knjizi.
Prvo smo se upoznali sa Bulovom logikom, ako se osvrnemo unazad, nakon to smo proli kroz
celo predavanje postaje jasno da su nae poetne pretpostavke bile tane, tj. da je ova tema
veoma bitna kada se radi o implementaciji grananja i petlji. Vrlo je vano dobro se upoznati
sa operatorima i tehnikama koje su ovde opisane.
Grananje nam omoguava da uslovno izvravamo kod, to kad se kombinuje sa petljama,
stvara kombinovane strukture u naem C# kodu. Kada imate petlje unutar petlji, unutar
iskaza if unutar petlji, poinjete da shvatate zato je uvlaenje koda bitno. Ako sav kod
pomerimo uz levu ivicu ekrana, odmah postaje teak za itanje i jo tei za otklanjanje
greaka. Ako ste shvatili I uvlaenja redova u kodu - ceniete to znanje kasnije. VS e uraditi
dosta toga za nas, ali nije lose da se tokom pisanja jo malo uvlae redovi.

Vebe

1. Ako imamo dve celobrojne vrednosti smetene u promenljive var 1 i var2, koji logiki test
moemo izvesti da bismo videli da li je jedna ili druga (ali ne obe) vea od 10?
2. Napiite aplikaciju koja ukljuuje logiku iz vebe 1, i koja dobija dva broja od korisnika i
prikazuje ih, ali odbacuje bilo koji unos koji je vei od 10 i tad trai dva nova broja.
3. Sta nije u redu sa sledeim kodom?
int i;
for (i=1;i<=10;i++)
{
if ((i % 2) = 0)
continue;
Console.WriteLine (i) ;
}
4. Izmenite aplikaciju Mandelbrotovog skupa tako da zatrai granice slike od korisnika i
prikae odabrani deo slike. Trenutni izlaz koda prikazuje onoliko znakova koliko moe stati u
jedan red konzolne aplikacije, pa vodite rauna o tome da svaka slika moe stati u isti
prostor, da bi se poveao vidljivi prostor.

24

Funkcije
Kod koji smo do sada videli uglavnom je bio smeten unutar jednog bloka, eventualno sa neto
petlji da bi se deo koda ponovio, ili grananja radi uslovnog izvravanja iskaza. Izvoenje
operacije nad podacima podrazumevalo je postavljanje koda na tano odreeno mesto gde on
treba da funkcionie.
Takva programska struktura je ograniena. esto emo nailaziti na zadatke (kao to je
pronalaenje najvee vrednosti unutar niza) koji se moraju izvriti nekoliko puta tokom izvrenja
programa. Moemo postaviti identine (ili priblino identine) delove koda u aplikaciju tamo gde
je to potrebno, ali mogu se pojaviti problemi. Ako napravimo najmanju izmenu u takvom delu
koda koji se tie nekog standardnog postupka (npr. ispravljanje greke u kodu), taj deo koda
moramo izmeniti na svim ostalim mestima unutar aplikacije. Ukoliko samo jedno od njih
propustimo da ispravimo, posledice mogu biti dramatine i dovesti do toga da kompletna
aplikacija ne radi. Pored toga, sama aplikacija bi bila vrlo velika.
Ovaj problem reavamo uz pomo funkcija. Funkcije u jeziku C# predstavljaju sredstva kojima se
obezbeuje blok koda koji moe biti izvren na bilo kom mestu u aplikaciji.
Funkcije odreenog tipa koje se nalaze u ovom predavanju poznate su kao metode. Iako ovaj
termin ima vrlo odreeno znaenje u .NET programiranju, za sada cento izbegavati njegovu
upotrebu.
Na primer, funkciju koja pronalazi maksimalnu vrednost u nizu moemo koristiti na bilo kom
mestu u programu i svaki put iskoristiti iste redove koda. Potrebno je da samo jednom
napiemo kod, i svaka promena koju unesemo odrazie se na sva mesta na kojima se kod
izvrava. To znai da funkcija sadri kod koji se moe iznova upotrebljavati.
Prednost funkcija je u tome to ine kod itljivijim, a takoe ih moemo koristiti za grupisanje
meusobno povezanog koda. Koristei funkcije smanjujemo glavni deo koda u aplikaciji, zato
to se sporedni delovi izvravaju izvan glavnog. To podsea na sabijanje velikih delova koda u
VS-u unutar prozora outline view, a daje i loginiju struktura aplikaciji.
Funkcije se takoe mogu koristiti pri pravljenju vienamenskog koda, jer one mogu izvriti
iste operacije nad razliitim podacima. Funkciju moemo snabdeti potrebnim informacijama u
obliku
parametara, a rezultate funkcija moemo dobiti u obliku povratnih vrednosti. Za gornji
primer, parametar bi bio niz koji se pretrauje, dok bi povratna vrednost bila maksimalna
vrednost unutar niza. To znai da istu funkciju moemo koristiti za rad sa razliitim nizovima.
Parametri i povratne vrednosti funkcije zajedno definiu potpis funkcije.
U ovom predavanju emo videti na koji nain se definiu proste funkcije koje niti primaju niti
vraaju podatke. Zatim emo videti kako se podaci prenose u funkciju i iz nje.
Nakon toga, obradiemo temu opsega vaenja promenljive. Ova tema se bavi nainom na koji
se podaci u C#-u lokalizuju u posebne delove koda - to dobija na znaaju kada delimo kod na
vise razliitih funkcija.
Upoznaemo se sa vrlo vanom funkcijom u C# aplikacijama - Main(). Videemo kako da
iskoristimo ve ugraene modele ove funkcije, da bismo iskoristili argumente iz komandne
linije, koji nam dozvoljavaju transfer informacija u aplikacije kada se one pokrenu.
Pogledaemo dodatne mogunosti struktura pomou kojih funkcije predstavljamo kao lanove
struktura. Na kraju emo upoznati dve naprednije teme: preoptereivanje funkcije i delegate.
Preoptereivanje funkcije je tehnika koja se koristi za stvaranje razliitih funkcija sa istim
imenom ali razliitim potpisom. Delegat je tip promenljive koji nam dozvoljava indirektno
korienje funkcije. Jedan delegat se moe koristiti za pozivanje bilo koje funkcije koja ima
odreeni potpis, to nam omoguava da biramo izmeu razliitih funkcija u toku izvrenja
programa.
1

Definisanje i korienje funkcija

U ovom delu emo videti kako da aplikaciji dodamo funkciju i zatim je koristimo (pozivamo) iz
koda. Poeemo od osnova, sa prostom funkcijom koja ne menja podatke sa kodom koji je
poziva; zatim emo videti napredniju upotrebu funkcija.

Veba br. 9.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole). U okviru za tekst Location;promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba9
(ovaj e direktorijum biti automatski napravljen ukoliko ve ne postoji), i ostavite
podrazumevani tekst u okviru za tekst Name: PrimerFunkcije1
Dodajte sledei kod u Class1.cs:

Pokrenite program birajui Debug | Start Without Debugging

Kako to radi
Sledea etiri reda vaeg koda definiu funkciju pod imenom Write() :

Ovaj kod jednostavno ispisuje tekst u konzolni prozor. Od toga su trenutno bitniji mehanizmi
koji stoje iza definicije, kao i upotrebe funkcije.Definicija funkcije se sastoji iz sledeeg:
dve kljune rei - static i void,
imena funkcija koje prate zagrade Write(),
bloka koda koji se izvrava uokviren zagradama.

Kod koji definie funkciju Write() vrlo je slian dragim redovima koda u aplikaciji:
static void Main (string [] args)
{
........
........
}
Sav kod koji smo do sada napisali (izuzev definicija tipova) bio je deo jedne funkcije. Funkcija
Main() je ulazna taka za konzolnu aplikaciju. Kada se C# aplikacija izvrava, poziva se
funkcija koja sadri ulaznu taku. Kada se ta funkcija izvri, aplikacija se zavrava. Sav izvrni
kod u jeziku C# mora imati ulaznu taku.
Jedina razlika izmeu funkcije Main() i funkcije Write() (izuzev redova koda koji se nalaze u
njima) jeste u tome to unutar zagrada posle imena funkcije Main postoji neki kod. Na taj
nain se navode parametri o kojima emo uskoro detaljnije govoriti.
Kako je gore pomenuto, Main () i Write () su definisane uz pomo kljunih rei static i void.
Kljuna re static odnosi se na objektno orijentisane koncepte. Za sada jedino treba zapamtiti
da sve funkcije koje emo ovde koristiti u aplikacijama mogu koristiti ovu kljunu re.
Sa druge strane, kljunu re void je mnogo jednostavnije objasniti. Ona ukazuje na to da
funkcija ne vraa nikakvu vrednost. Kasnije emo videti ta treba navesti ukoliko funkcija
vraa neku vrednost.
Kod koji poziva funkciju je sledei:
Write() ;
Jednostavno unesemo ime funkcije sa praznim zagradama. Kada se u toku izvrenja programa
naie na ovu taku, izvrava se kod funkcije Write ().
Upamtite da su zagrade koje se koriste na oba mesta, prilikom definicije funkcije i dok je
pozivamo, obavezne. Ukoliko ih uklonite, kod se nee kompajlirati.

Povratne vrednosti

Najjednostavniji nain za razmenu podataka sa funkcijom jeste korienje povratne vrednosti.


Funkcija koja ima povratnu vrednost izraunava je na isti nain na koji se unutar izraza
izraunava vrednost promenljive. Povratne vrednosti, kao i promenljive, imaju svoj tip.
Na primer, moemo imati funkciju sa imenom getString() ija je povratna vrednost tipa string.
To moemo koristiti u kodu na sledei nain:
string mojString;
mojString = getString() ;
Moda emo imati funkciju pod imenom getVal() koja vraa vrednost tipa double, koju
moemo koristiti u matematikim izrazima:
double mojVal;
double multipler = 5.3;
mojVal = getVal() * multipler;
Kada funkcija vraa vrednost moramo je izmeniti na dva naina:
Moramo navesti tip povratne vrednosti u deklaraciji funkcije, umesto kljune rei void.
Moramo koristiti kljunu re return da bismo zavrili funkciju i preneli povratnu vrednost u
pozivajui kod.
Prikazano preko koda za tip funkcije konzolne aplikacije koju smo ve videli, to izgleda ovako:
Static <returnType> <functionName>()
{
..........
..........
return <returnValue>;
}
Jedino ogranienje je u tome da <returnValue> mora biti vrednost koja je tipa <returnType>,
ili moe biti implicitno konvertovana u taj tip. Pa ipak, <returnType> moe biti bilo koji tip,
ukljuujui komplikovanije tipove koje smo ve videli. To moe biti jednostavno, kao na
primer:
static double getVa()
{
return 3.2;
}
Meutim, povratne vrednosti su obino rezultat prorauna izvedenog unutar funkcije, jer se to
jednostavno moe postii sa promenljivom tipa const.
Kada doe do iskaza return, izvrenje programa se momentalno vraa na pozivajui kod.
Redovi unutar funkcije koji se nalaze iza ovog iskaza nee biti izvreni. To ipak ne znai da se
return mora postaviti na kraj funkcije. Iskaz return moemo koristiti pre toga, moda nakon
izvrenja nekog logikog grananja.

Postavljanje iskaza return u for petlju, blok if, ili neku slinu struk-turu, dovodi do trenutnog
zavretka strukture i funkcije. Na primer:
static double getVal()
{
double checkVal;
// checkVal je dodeljena vrednost kroz neku logiku
if (checkVal < 5)
return 4.7;
return 3.2;
}
Ovde moe biti vraena jedna od dve vrednosti, zavisno od vrednosti u checkVal.
Jedino ogranienje je da iskaz return mora biti izvren pre nego to se dostigne krajnja
oznaka funkcije }. Sledee nije dozvoljeno:
static double getVal()
{
double checkVal;
// checkVal je dodeljena vrednost kroz neku logiku
if (checkVal < 5)
return 4.7;
}
Ako je checkVal >= 5, onda se iskaz return nee izvriti, to nije dozvoljeno. Sve putanje kroz
funkciju se moraju zavriti jednim iskazom return.
Iskaz return se moe koristiti u funkcijama koje se deklariu pomou kljune rei void, koje
nemaju povratnu vrednost. Ako to uradimo, funkcija e se zaustaviti. Kada koristimo iskaz
return na ovaj nain, pogreno je navesti povratnu vrednost izmeu kljune rei return i
take-zareza iza nje.

Parametri

Kada funkcija treba da prihvati parametre, moramo navesti sledee:


listu parametara koje funkcija prihvata, zajedno sa njihovim tipovima unutar
definicije funkcije,
odgovarajuu listu parametara u svakom pozivu funkcije.
Podrazumeva se sledei kod:
Static <returnType> <functionName>(<paramType> <paramName>, ...)
{
........
........
return <returnValue>;
}
Ovde moemo imati proizvoljan broj parametara, svaki sa tipom i imenom. Parametri su
odvojeni zarezima. Svakom od parametara se moe pristupiti unutar funkcije kao
promenljivoj.

Na primer, prosta funkcija moe imati dva parametra tipa double i vratiti njihov proizvod:
static double product (double param1, double param2)
{
return param1 * param2;
}
Pogledajmo malo sloeniji primer.

Veba br. 10.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba10 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerFunkcije2
Dodajte sledei kod u Class1.cs:

Pokrenite program.

Kako to radi
Ovaj kod sadri funkciju koja radi ono emu smo se nadali u primeru funkcije u uvodu ovog
predavanja: prihvata niz celih brojeva kao parametre i vraa najveu vrednost tog niza.
Definicija funkcije je sledea:

Funkcija MaxVrednost() ima samo jedan definisani parametar - niz tipa int pod imenom
intArray. Takoe ima povratnu vrednost tipa int. Izraunavanje maksimalne vrednosti je
jednostavno. Lokalnoj promenljivoj maxProm tipa int dodeljena je prva vrednost u nizu, a
zatim se ova vrednost poredi sa svakim sledeim elementom u nizu. Ako element sadri veu
vrednost od maxProm, ova vrednost zamenjuje trenutnu vrednost u maxProm. Kada se petlja
zavri, maxProm sadri najveu vrednost u nizu i vraa se pomou iskaza return.
Kod u funkciji Main() deklarie i inicijalizuje prost celobrojni niz koji koristimo u funkciji
maxVrednost():
int[] mojArray = (1, 8, 3, 6, 2, 5, 9, 3, 0, 2};
Poziv funkcije maxVrednost() se koristi da bi se dodelila vrednost promenljivoj maxProm tipa
int maxProm = maxVrednost (mojArray);
Sledei korak je ispisivanje ove vrednosti na ekran korienjem komande Console.WriteLine():
Console.WriteLine(Maksimalna vrednost u nizu mojArray je {0}, maxProm);

Slaganje parametara
Kada pozivamo funkciju moramo sloiti parametre tano kao to je navedeno u definiciji
funkcije, odnosno moramo sloiti tipove parametara, njihov broj i redosled. To znai da se
sledea funkcija:
Static void myFunction(string myString, double myDouble)
{
.....
.....
}
ne moe se pozvati sa:
myFunction(2.6, "Hello");
7

Ovde pokuavamo da prosledimo vrednost tipa double kao prvi parametar, a vrednost tipa
string kao drugi, to nije redosled po kome su parametri navedeni u definiciji funkcije.
Takoe ne moemo koristiti:
myFunction("Hello");
Ovde prosleujemo samo jedan parametar tipa string, a zahtevaju se dva. Ako pokuamo da
koristimo bilo koji od ova dva poziva, doi e do greke pri kompajliranju, jer nas kompajler
primorava da sloimo parametre u funkcijama koje koristimo.
Ako se vratimo naem primeru - to znai da funkciju maxVrednost() moemo koristiti samo za
dobijanje maksimalne vrednosti u nizu celih brojeva. Ako zamenimo kod u funkciji Main()
sledeim kodom:

kod se nee kompajlirati zato to je tip parametra pogrean.


Kasnije u ovom predavanju, u delu koji se bavi preoptereenjem operatora, videemo tehniku
koja zaobilazi ovaj problem.

Nizovi parametara
C# nam dozvoljava da definiemo jedan (i samo jedan) poseban parametar za funkciju. Ovaj
parametar, koji mora biti zadnji u listi parametara u definiciji funkcije, poznat je kao niz
parametara. Nizovi parametara dozvoljavaju nam da pozivamo funkcije koristei promenljivu
koliinu parametara, a definisani su kljunom rei params.
Nizovi parametara mogu biti korisni za pojednostavljivanje koda, jer ne moramo prosleivati
nizove iz naeg pozivajueg koda. Umesto toga, prosleujemo nekoliko parametara istog tipa,
koji se nalaze u nizu koji moemo koristiti unutar funkcije.
Sledei kod je potreban da bi se definisala funkcija koja koristi niz parametara:
static <returnType> <functionName>(<p1Type><p1Name>, . . . , params <type> []
<name>)
{
.....
.....
return <returnValue>;
}
Ovu funkciju moemo pozvati sa:
<functionName>(<p1>,...,<val1><val2>,...)

Ovde su <val1>, <val2> i tako dalje, vrednosti tipa <type> koji je korien da bi se
inicijalizovao niz <name>. Ne postoji ogranienje u broju parametara koje moemo navesti;
jedino ogranienje je da su svi tipa <type>. Cak i ne moramo navoditi parametre.
Poslednja stavka ini nizove parametara posebno korisnim za navoenje dodatnih informacija
koje e funkcije koristiti tokom izvrenja. Na primer, imamo funkciju pod imenom getWord (),
koja uzima vrednost tipa string kao prvi parametar i vraa prvu re u nizu znakova:
string firstWord = getWord("Ovo je reenica.");
Ovde e promenljivoj firstWord biti dodeljena vrednost "Ovo" .
Moemo dodati parametar params u funkciju getWord(), to nam dozvoljava da vratimo
alternativnu re po njenom indeksu:
string firstWord = getWord("Ovo je reenica.",2);
Ako pretpostavimo da smo poeli brojanje od 1 za prvu re, rezultat e biti to da je
promenljivoj firstWord dodeljena vrednost "je".
Takoe, moemo dodati mogunost ogranienja broja znakova koji se vraaju preko treeg
parametra, kojem se takoe moe pristupiti preko parametra params:
string firstWord = getWord("Ovo je reenica.",3,3);
Ovde e promenljivoj firstWord biti dodeljen string "re".

Veba br. 11.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba11 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerParametara. Dodajte sledei kod u Class1.cs:

Pokrenite program

Kako to radi
U ovom primeru je funkcija sumProm() definisana pomou kljune rei params, tako da
prihvati proizvoljan broj parametara tipa int (i nijedne drage):
static int sumProm (params int[] vals)
{
.......
.......
}
Kod u ovoj funkciji iterativno prolazi kroz vrednosti u nizu vals, sabira vrednosti zajedno,
vraajui rezultat.
U funkciji Main() pozivamo funkciju sa pet celobrojnih parametara:
int sum = sumProm(1, 5, 2, 9, 8);
Meutim, ovu funkciju smo mogli pozvati bez i jednog, sa jednim, dva, ili stotinu celobrojnih
parametara - ne postoji ogranienje u koliini parametara koje moemo navesti.

Prenos parametara po referenci i vrednosti

Funkcije koje smo do sada naveli koristile su prenos parametara po vrednosti. Podrazumeva se
da smo, koriste parametre, prosleivali njihove vrednosti u promenljive koje koristi funkcija.
Bilo koja promena nad promenljivom unutar funkcije nema nikakvog efekta na parametre
navedene u pozivu funkcije. Na primer, razmotrite funkciju koja udvostruuje i prikazuje
vrednost prosleenog parametra:
static void DupliranaVred(int prom)
{
prom *=2;
Console.WriteLine("duplirana promenljiva = (0)", prom);
}
Ovde je parametar prom udvostruen unutar funkcije. Ako je pozovemo na sledei nain:
int mojBroj = 5;
Console.WriteLine("mojBroj = {0]", mojBroj);
DupliranaVred (mojBroj) ;
Console.WriteLine("mojBroj = (0) ", mojBroj);
- na konzoli e se pojaviti tekst:
mojBroj = 5
duplirana promenljiva = 10
mojBroj = 5
10

Pozivanje funkcije DupliranaVred() sa promenljivom mojBroj kao parametrom, ne utie na


vrednost mojBroj unutar bloka Main(), iako je parametar val koji joj je dodeljen udvostruen.
Ako poelimo da se vrednost promenljive mojBroj promeni, eto problema. Moemo koristiti
funkciju koja vraa novu vrednost za mojBroj, a pozivamo je sa:
int mojBroj = 5;
Console.WriteLine{"mojBroj = {0)", mojBroj);
mojBroj = DupliranaVred(mojBroj) ;
Console.WriteLine("mojBroj = (0)", mojBroj);
Ovaj kod teko da je intuitivan i nee se izboriti sa promenom vrednosti za vise promenljivih
koje se koriste kao parametri (jer funkcija ima samo jednu povratnu vrednost).
Umesto toga, elimo da prosledimo parametar po referenci. To znai da e funkcija raditi sa
potpuno istom promenljivom kao u pozivu funkcije, a ne samo sa promenljivom koja ima istu
vrednost. Sve promene koje se deavaju toj promenljivoj odrazie se na promenljivu koja se
koristi kao parametar. Da bi se ovo uradilo, treba jednostavno upotrebiti kljunu re ref za
navoenje parametra:
static void DupliranaVred (ref int prom)
{
prom *= 2;
Console.WriteLine("duplirana promenljiva = (0)", prom);
}
Ponovimo to u pozivu funkcije (to je obavezno, jer je parametar tipa ref deo potpisa same
funkcije):
int mojBroj = 5;
Console.WriteLine("mojBroj = (0)", mojBroj);
DupliranaVred (ref mojBroj);
Console.WriteLine("mojBroj = (0}", mojBroj);
Tada bi izlazni tekst na konzoli bio sledei:
mojBroj = 5
duplirana promenljiva = 10
mojBroj = 10
Ovoga puta je promenljiva mojBroj izmenjena od strane funkcije DupliranaVred(). Postoje
dva ogranienja u vezi sa promenljivom koja se koristi kao ref parametar. Prvo - funkcija
moe prouzrokovati promenu vrednosti u referentnom parametru, tako da moramo koristiti
promenljivu koja nije konstanta u okviru poziva funkcije. Zbog toga nije dozvoljeno sledee:
const int mojBroj = 5;
Console.WriteLine("mojBroj = (0)", mojBroj);
DupliranaVred (ref mojBroj) ;
Console.WriteLine("mojBroj = (0)", mojBroj);
Drago - promenljiva koju koristimo mora"biti inicijalizovana. Jezik C# nam ne dozvoljava
pretpostavku da e parametar ref biti inicijalizovati u funkciji koja ga upotrebljava. Sledei
kod nije dozvoljen:
int mojBroj
DupliranaVred (ref mojBroj);
Console.WriteLine("mojBroj = {0}", mojBroj);

11

Izlazni parametri

Moemo definisati da je dati parametar izlazni parametar, preko kljune rei out koja se
koristi na isti nain kao i kljuna re ref (kao modifikator parametra u definiciji funkcije, i pri
njenom pozivanju). Rezultat toga je isto ponaanje kao i kod referentnog parametra, u smislu
da se vrednost parametra na kraju funkcije vraa promenljivoj koja je upotrebljena u njenom
pozivu. Meutim, postoje i vane razlike. Dok za parametre tipa ref nije dozvoljeno koristiti
promenljive kojima nije dodeljena vrednost, kod parametara out to moemo raditi. Pored
toga, out parametar se mora tretirati kao da mu nije dodeljena vrednost od strane funkcije
koja ga koristi. To znai da, iako je dozvoljeno koristiti promenljivu kojoj je dodeljena
vrednost kao izlazni parametar, vrednost koju ona sadri u pozivu funkcije bie izgubljena
nakon izvrenja te funkcije.
Na primer, razmotrite proirenje funkcije MaxVrednost() koju smo ranije videli, a koja vraa
najveu vrednost u nizu. Izmeniemo funkciju tako da vrati indeks elementa sa najveom
vrednosti unutar niza. Da bi bilo jednostavnije, vratiemo samo indeks prve pojave najveeg
elementa, ukoliko ih ima vise. Da bismo ovo uradili dodajemo izlazni parametar menjajui
funkciju na sledei nain:
static int MaxVrednost(int[] intArray, out in maxIndex)
{
int maxProm = intArray [0];
maxIndex =0;
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxProm)
{
maxProm = intArray [i] ;
maxIndex = i;
}
return maxProm;
}
Moemo koristiti funkciju na sledei nain:
int [] myArray = (1, 8, 3, 6, 2, 5, 9, 3, 0, 2);
int maxIndex
Console.Write("Maksimalna vrednost u nizu myArray je {0)", MaxVrednost(myArray,
out maxIndex);
Console.WriteLine{"Maksimalna vrednost niza je (0) element u nizu", maxindex+1);
Rezultat ovoga je:
Maksimalna vrednost u nizu myArray je 9
Maksimalna vrednost niza je 7 element u nizu
Ovde je vano naglasiti da se kljuna re out mora upotrebiti u pozivu funkcije, ba kao i
kljuna re ref.
Upamtite daje vrednosti maxIndex dodato jedan, i vraa se ovde dok je ispisujemo na ekran.
To je zato da bismo indeks preveli u razumljiviji oblik, tako da se prvi element u nizu ne
oznaava sa 0 ve sa 1.

12

Opseg vaenja promenljive

Moda ste se upitali zato je uopte potrebna razmena podataka sa funkcijama. Razlog je taj
to se promenljivama u C#-u moe pristupiti samo iz lokalnih regiona koda. Za datu
promenljivu kae se da ima opseg vaenja unutar koga joj se moe pristupiti.
Opseg vaenja promenljive je vana tema i najbolje emo je predstaviti preko primera.
Definisanje i korienje osnovnih funkcija.

Veba br. 12.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba12 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerOpsegParam. Dodajte sledei kod u Class1.cs:

Kompajlirajte kod i obratite panju na greku i upozorenje koji se pojavljuju u listi zadataka:

13

Kako to radi
Sta je krenulo loe? Promenljivoj mojString, definisanoj u glavnom delu programa (u funkciji
Main ()), nije mogue pristupiti iz funkcije Write ().
Razlog za ovu nepristupanost jeste to to promenljiva ima svoje podruje vaenja unutar
koga je validna. To podruje podrazumeva blok koda u kom je deformisana i bilo koje direktno
ugnedene blokove koda. Blokovi koda u funkcijama odvojeni su od blokova koda iz kojih se
pozivaju.
Unutar funkcije Write() ime mojString je nedefinisano, pa je i promenljiva mojString
deformisana u funkciji Main() van opsega vaenja - ona se moe koristiti samo u funkciji
Main().
Moemo imati potpuno nezavisnu promenljivu u funkciji Write(), nazvanu mojString. Pokuajte
da izmenite kod na sledei nain:

Veba br. 13.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba13 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerParam2. Dodajte sledei kod u Class1.cs:

Ovaj kod e se kompajlirati i rezultat e biti:

14

Operacije koje izvodi ovaj kod su sledee:


Main() definie i inicijalizuje promenljivu tipa string sa imenom mojString.
Main() prebacuje kontrolu na funkciju Write().
Write() definie i inicijalizuje promenljivu tipa string sa imenom mojString, koja nije isto
to i promenljiva mojString definisana u funkciji Main().
Write() ispisuje niz znakova na konzolu koji sadri vrednost mojString definisan unutar
funkcije Write().
Write() vraa kontrolu funkciji Main().
Main()
Main().

ispisuje na konzolu vrednost koju sadri mojString definisan unutar funkcije

Promenljive iji opseg vaenja na ovaj nain pokriva samo jednu funkciju, poznate su kao
lokalne promenljive. Takoe je mogue imati globalne promenljive, iji opseg vaenja
pokriva vie funkcija. Izmenite kod na sledei nain:

15

Rezultat je sada:

Ovde smo dodali jo jednu promenljivu pod imenom mojString, ovaj put na viem nivou
hijerarhije imena. Ova promenljiva je definisana na sledei nain:
static string mojString;
Primetiete da opet koristimo kljunu re static. Pomenimo da u konzolnim aplikacijama, pri
navoenju globalnih promenljivih u ovom obliku, moramo koristiti kljune rei static ili const.
Ako elimo da menjamo vrednost globalne promenljive, moramo navesti static, jer const
zabranjuje menjanje vrednosti promenljive.
Da bismo napravili razliku izmeu ove promenljive i lokalnih promenljivih istog imena u
funkcijama Main() i Write(), moramo se obratiti promenljivoj koristei puno kvalifikovano
ime. Ovde se globalnoj promenljivoj obraamo sa Class1.mojString. To je neophodno samo
kada imamo globalne i lokalne promenljive sa istim imenom. Kada ne bi bilo lokalne
promenljive mojString, globalnu promenljivu bismo mogli upotrebljavati jednostavno sa
mojString umesto Class1.mojString. Kada imamo lokalnu promenljivu koja ima isto ime kao i
globalna promenljiva, za globalnu se kae da je skrivena.
Vrednost globalne promenljive postavljena je u funkciju Main() sa:
Class1.mojString = "Globalni string";
A unutar funkcije Write() pristupa joj se sa:
Console.WriteLine("Globalni mojString = (0)", Class1.mojString);
Sigurno se pitate zato ne bismo ovu tehniku koristili za razmenu podataka sa funkcijama,
umesto to dodajemo parametre kako smo ranije videli. Postoje situacije kada je ovakav nain
poeljniji za razmenu podataka, ali ih ima isto toliko (ako ne i vise) kod kojih to nije sluaj.
Izbor - da li koristiti globalnu promenljivu, zasniva se na nainu na koji e se koristiti funkcija.
Globalne promenljive uglavnom nisu pogodne za opte namenske funkcije koje su sposobne da
rade sa bilo kojim podacima koje obezbedimo, i nisu ograniene samo na podatke u
specifinim globalnim promenljivama. Kasnije emo detaljnije govoriti o tome.

Opseg vaenja promenljive u drugim strukturama

Jedna od stvari koju smo objasnili u prolom delu ima posledice na opseg vaenja izvan
funkcija. Opseg vaenja promenljivih ukljuuje blok koda u kom su definisane, i bilo koje
direktno ugnedene blokove koda. To se odnosi i na druge blokove koda, kao to su grananja i
petlje. Razmotrite sledei kod:

16

Veba br. 14.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba14 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerOpsegParam2. Dodajte sledei kod u Class1.cs:

Ovde je promenljiva tipa string pod imenom text lokalna za for petlju. Taj kod se nee
kompajlirati zato to poziv za Console.WriteLine(), koji se dogaa van petlje, pokuava da
koristi promenljivu text koja je izvan opsega vaenja kada je van petlje. Pokuajte da
promenite kod na sledei nain:

17

Ovaj kod takoe nee raditi zbog toga to promenljiva mora biti deklarisana i inicijalizovana
pre upotrebe, a text je inicijalizovana samo u for petlji. Vrednost dodeljena promenljivoj text
gubi se kada se izae iz petlje. Ipak, moemo napraviti sledeu promenu:

Promenljiva text e biti inicijalizovana van petlje pa moemo pristupiti njenoj vrednosti.
Rezultat ovog jednostavnog koda je sledei:

Ovde je poslednja vrednost, dodeljena promenljivoj text u petlji, dostupna i izvan petlje.
U svetlu prethodnih primera, nije odmah oigledno zato promenljiva text posle petlje ne
zadrava prazan niz znakova koji joj je dodeljen pre petlje.
Objanjenje za to tie se memorijske dodele za promenljivu text kao i bilo koje druge
promenljive. Samim deklarisanjem osnovnog tipa promenljive ne postie se mnogo. Tek kada
se dodele vrednosti, one se rasporeuju u memoriji. Kada se ova raspodela dogodi unutar
petlje, vrednost je deformisana kao lokalna i izlazi izvan opsega vaenja kada je van petlje.
Iako sama promenljiva nije lokalnog karaktera za petlju, vrednost koju sadri jeste.
Dodeljivanje vrednosti izvan petlje omoguava da ta vrednost postane lokalna za glavni deo
koda, a da i dalje bude u opsegu unutar petlje. To znai da promenljiva ne izlazi iz svog
opsega vaenja, dokle god ne izae iz bloka glavnog dela koda, tako da imamo pristup njenim
vrednostima izvan petlje.

18

C# kompajler e otkriti probleme vezane za opseg vaenja promenljivih i reagovae poruka o


greci, koja nam pomae da shvatimo problem opsega vaenja promenljivih.
Uopteno, vredi deklarisati i inicijalizovati sve promenljive pre nego to ih iskoristimo u bilo
kom bloku koda. Izuzetak je deklarisanje promenljivih za petlju kao deo bloka unutar petlje,
na primer:
for (int i+0; i<10; i++)
{
.....
.....
{
Ovde je promenljiva i lokalizovana na blok koda u petlji, ali to prihvatljivo, jer e nam ovaj
broja retko zatrebati u kodu izvan petlje.

Parametri i povratne vrednosti nasuprot globalnim


podacima

U ovom delu emo blie pogledati razmenu podataka sa funkcijama preko globalnih podataka,
i preko parametara i povratnih vrednosti. Da se podsetimo - govorimo o razlici izmedu koda
kao to je:

Veba br. 15.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba15 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerPovrVred. Dodajte sledei kod u Class1.cs:

19

Ovaj kod se malo razlikuje od koda koji smo videli ranije, kada smo koristili promenljivu sa
imenom mojBroj u funkciji Main(). To je primer da lokalne promenljive mogu imati ista
imena i da pritom ne smetaju jedna drugoj. To takoe znai da su ova dva primera koda
slina, to nam dopusta da se fokusiramo na specifikacije razlike, ne vodei brigu o imenima
promenljivih.

Rezultat ovih funkcije je identian.

Ne postoji vrsto pravilo koje e odrediti koju od ove dve metode da koristimo, jer su obe
tehnike savreno ispravne. Pa ipak, ima nekoliko saveta koje treba razmotriti.
Za poetak - showDouble() verzija koja koristi globalnu vrednost uvek e koristiti globalnu
promenljivu val. Da bismo koristili ovu verziju, moramo koristiti globalnu promenljivu. To
ograniava raznolikost funkcija i znai da stalno moramo kopirati vrednost globalne
promenljive u druge promenljive ako hoemo da smestimo rezultate. Pored toga, globalni
podaci mogu biti modifikovani iz nekog drugog koda u aplikaciji, to moe prouzrokovati
nepredvidive rezultate (vrednosti bi se mogle promeniti, a mi bismo kasno za to saznali).
Ovaj gubitak raznolikosti esto moe biti dobitak. Bie trenutaka kada emo poeleti da
koristimo funkciju samo za jednu namenu, a korienje globalnih podataka smanjuje
mogunost greke u pozivu funkcije (moda dodavanjem pogrene promenljive).
Naravno, moe se govoriti o tome da ova jednostavnost ini na kod manje razumljivim.
Eksplicitno navoenje parametara dozvoljava nam da na prvi pogled vidimo ta se menja. Ako
vidimo poziv koji je, recimo, myFunction (var1, out var2), odmah znamo da su var1 i var2
20

vane promenljive koje emo uzeti u obzir, kao i da e promenljivoj var2 biti dodeljena nova
vrednost kada se funkcija izvri. Suprotno tome, ako funkcija ne prima nikakve parametre, ne
moemo pretpostaviti kojim se podacima manipulie unutar nje.
Treba zapamtiti da nije uvek mogue koristiti globalne podatke. Kasnije u knjizi emo video
kod koji je napisan u razliitim datotekama i/ili pripada razliitim imenovanim prostorima koji
komuniciraju izmeu sebe preko funkcija. U ovakvim sluajevima, kod je toliko izdeljen na
nezavisne celine, da ne postoji oigledan izbor za korienje globalnih lokacija za
skladitenje.
Da sumiramo - slobodno koristite obe tehnike za razmenu podataka. Savet je da koristite
parametre pre nego globalne promenljive, ali postoje odreeni sluajevi kada su globalni
podaci mnogo pogodniji i sigurno nije greka koristiti ovu tehniku.

Funkcija Main()

Preli smo vei deo tehnika koje se koriste u kreiranju i upotrebi funkcija. Sada emo se
vratiti unazad da izbliza pogledamo funkciju Main().
Rekli smo za funkciju Main () da je ulazna taka za C# aplikaciju i da izvrenje ove funkcije
prati izvrenje same aplikacije. Takoe smo videli da ova funkcija ima parametar string[ ]
args, ali jo nismo videli ta taj parametar predstavlja. Videemo ta je ovaj parametar i kako
se upotrebljava.
Upamtite da postoje etiri razliita potpisa koja moemo koristiti za funkciju Main():
static void Main(),
static void Main(string[] args),
static int Main(),
static int Main(string [] args).
Moemo izostaviti argument args koji je ovde naveden. Verziju sa argumentom koriten jer se
ona automatski pravi kada pravimo konzolnu aplikaciju u VS-u.
Trea i etvrta verzija vraaju vrednost tipa int, koju moemo koristiti da oznaimo kako e
se zavriti aplikacija, a esto se koristi da bi ukazala na greku. Uopteno, vraena vrednost 0
oznaava da se program normalno zavrio (odnosno, da se aplikacija izvrila i da se moe
zaustaviti na siguran nain).
Parametar args funkcije Main() metod je za prihvatanje informacija izvan aplikacije,
navedenih u toku izvrenja programa. Ova informacija uzima oblik parametara komandne
linije.
Kada izvravamo aplikaciju preko komandne linije, esto smo u mogunosti da direktno
navedemo informaciju kao to je datoteka koja se uitava u izvrenju aplikacije. Na primer,
pogledajte aplikaciju Notepad u Windowsu. Moemo je pokrenuti tako to upiemo notepad u
komandnu liniju, ili u okviru prozora koji se pojavljuje kada odaberemo opciju Run iz Windows
menija Start. Takoe, moemo uneti neto nalik na notepad "myfile.txt" na ovim lokacijama.
Rezultat e biti to da e Notepad uitati datoteku "myfile.txt" kada se pokrene, ili e ponuditi
da napravi ovu datoteku. Ovde je "myfile.txt" argument komandne linije. Moemo napisati
konzolnu aplikaciju koja radi na slian nain koristei parametar args.
Kada se konzolna aplikacija pokrene, svaki parametar komandne linije koji je naveden smeta
se u niz args. Zatim te parametre moemo koristiti u aplikaciji.
21

Pogledajmo praktini primer toga.

Veba br. 16.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba16 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerFjaMain. Dodajte sledei kod u Class1.cs:

Otvorite stranicu sa svojstvima projekta (pritisnite ime projekta PrimerFjaMain desnim


tasterom mia u prozora Solution Explorer i izaberite Properties).
Izaberite stranicu Configuration Properties I Debbuging i dodajte argumente komandne linije
koje elite u polje Command Line Arguments:

22

Pokrenite aplikaciju.

Kako to radi
Kod koji se koristi ovde vrlo je jednostavan:

Parametar args koristimo kao bilo koji drugi niz tipa string - samo ispisujemo na ekran ta je
definisano.
U ovom primeru obezbedili smo argumente kroz dijalog Project Properties u VS-u. To je od
pomoi kada se koriste isti argumenti komandne linije pri startovanju aplikacije iz VS-a,
umesto da se svaki put unose u komandnu liniju. Isti rezultat bi se postigao kada bismo otvorili
komandnu liniju u istom direktorijumu u kome se nalazi izlaz projekta
(C:\Temp\SoftIng\LecturesCode\Vezba16\bin\Debug), i zatim upiemo sledee:
256 mojFajl.txt "duzi argument"
Upamtite da je svaki argument od narednog odvojen razmakom, ali argumente moemo
navesti i u navodnicima ako elimo dui argument (to je neophodno ako argument ukljuuje
razmake, da se ne bi interpretirao kao vise argumenata).

Funkcije lanice struktura

Tip struct slui za smetanje razliitih elemenata podataka na jedno mesto. Strukture su
sposobne i za mnogo vise od toga. Vana dodatna sposobnost koju nude jeste mogunost da
sadre funkcije isto kao i podatke. Ovo na prvi pogled moe delovati udno, ali je u stvari
izuzetno korisno.
Kao jednostavan primer, razmotrite sledeu strukturu:
struct ImeKupac
{
public string Ime, Prezime;
}
Ako imamo promenljivu tipa ImeKupac, a elimo da ispiemo njeno puno ime na konzoli,
moraemo da napravimo ime iz sastavnih delova. Moemo koristiti sledeu sintaksu za
promenljivu tipa ImeKupac sa imenom kupac, na primer:
ImeKupac mojKupac;
mojKupac.Ime = "Petar";
mojKupac.Prezime = "Petrovi";
23

Console.WriteLine("(0} {1} ", kupac.Ime, kupac.Prezime);


Dodajui funkciju strukturi, ovo moemo pojednostaviti tako to emo centralizovati obradu
standardnih zadataka kao to je ovaj. Toj strukturi moemo dodati odgovarajuu funkciju na
sledei nain:
struct ImeKupac
{
public string Ime, Prezime;
public string ImePrezime()
{
return Ime + " " + Prezime;
}
}
Ovo lii na bilo koju funkciju koju smo do sada videli, osim to nije korien modifikator
static. Treba znati da ova kljuna re nije potrebna za funkcije lanica struktura. Tu funkciju
moemo koristiti na sledei nain:
ImeKupac mojKupac;
mojKupac.Ime = "Petar";
mojKupac.Prezime = "Petrovi";
Console.WriteLine (kupac.ImePrezime());
Sintaksa je mnogo jednostavnija i razumljivija u odnosu na prethodnu.
Vano je naglasiti da funkcija ImePrezime() ima direktan pristup lanovima strukture Ime i
Prezime. Oni se unutar strukture ImeKupac mogu smatrati globalnim.

Preoptereenje funkcija
Ranije u ovom predavanju smo videli da moramo sloiti potpis funkcije kada je pozivamo. To
znai da je potrebno imati dve funkcije koje operiu nad razliitim tipovima promenljivih.
Preoptereenje operatora prepoznaje ovu situaciju i omoguuje da napravimo vise razliitih
funkcija sa istim imenom, koje rade sa razliitim tipovima parametara.
Na primer, ranije smo koristili kod koji je sadrao funkciju pod imenom MaxVrednost():

24

Ova funkcija se moe koristiti samo za niz vrednosti tipa int. Moemo obezbediti funkcije sa
razliitim imenima za razliite tipove parametara, na primer promenom imena gornje funkcije
u
recimo,
IntArrayMaxVrednost(),
kao
i
dodavanjem
funkcije
kao
to
je
DoubleArrayMaxVrednost() da radi sa drugim tipovima. Umesto toga, moemo samo dodati
sledeu funkciju u na kod:

Razlika je u tome to ovde koristimo vrednosti tipa double. Ime funkcije MaxVrednost() je
isto, ali je njen potpis drugaiji. Bila bi greka definisati dve funkcije sa istim imenom i
potpisom, ali poto ove funkcije imaju razliit potpis, sve je u redu. Sada imamo dve verzije
MaxVrednost() koje prihvataju nizove tipa int i double, i u odnosu na to vraaju maksimalnu
vrednost tipa int ili double.
Prednost je u tome to ne moramo eksplicitno navoditi koju od ove dve funkcije elimo da
koristimo. Jednostavno obezbedimo niz parametara i prava funkcija e se izvriti u zavisnosti
od tipa parametra koji koristimo.
Vredi zapaziti jo jednu osobinu tehnologije intelisens u VS-u. Ako u aplikaciji imamo dve
malopre prikazane funkcije i krenemo da unosimo ime funkcije u (recimo) funkciji Main () , VS
e prikazati mogua preoptereena imena za tu funkciju. Ako unesemo sledee:
double result = MaxVrednost(
VS nam daje informacije o obe verzije funkcije MaxVrednost(), koje moemo birati koristei
tastere sa strelicama gore ili dole.

Kada preoptereujemo funkciju, svi aspekti potpisa funkcije bie ukljueni. Moemo imati dve
razliite funkcije koje uzimaju parametre po vrednosti ili po referenci:
static void showDouble(ref int val)
{
.........
.........
}
static void showDouble(int val)
{
..........
25

..........
}
Izbor - koju od ove dve verzije emo koristiti, zasnovan je na tome da li poziv funkcije sadri
kljunu re ref. Sledee bi pozvalo verziju sa prenosom po referenci:
showDouble (refval) ;
Sledee bi pozvalo verziju sa prenosom po vrednosti:
showDouble (val)
Alternativno, moemo imati funkcije koje se razlikuju po broju parametara koje zahtevaju i
tako dalje.

Delegati

Delegat je tip koji omoguuje uvanje referenci u funkcijama. Iako ovo zvui vrlo struno,
mehanizam je vrlo jednostavan. Najvaniju namenu delegata razjasniemo kada doemo do
dela knjige koji se bavi dogaajima i njihovom obradom. Kada kasnije budemo koristili
delegate bie nam poznati, to e omoguiti razumevanje nekih komplikovanijih tema.
Delegati se deklariu slino kao i funkcije, ali bez tela funkcije i uz upotrebu kljune red
delegate. Deklaracija delegata definie potpis funkcije koji sadri povratni tip i listu
parametara. Nakon definisanja delegata, moemo deklarisati promenljivu sa tipom tog
delegata. Zatim moemo inicijalizovati promenljivu tako da sadri referencu na bilo koju
funkciju koja ima isti potpis kao i delegat. Kada to uradimo, moemo pozvati funkciju
koristei promenljivu delegata kao da je funkcija.
Kada imamo promenljivu koja pokazuje na funkciju, moemo izvesti druge operacije koje bi
bilo nemogue izvesti nekom drugom metodom. Na primer, moemo proslediti delegat nekoj
funkciji kao parametar, zatim ta funkcija moe pomou delegata pozvati funkciju na koju on
ukazuje, ne znajui koja e to funkcija biti sve do izvrenja.

Veba br. 17.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta Console
Application u okviru prozora Templates: (za ovo ete morati malo da pomerite prozor na
dole).
U
okviru
za
tekst
Location;
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba17 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
PrimerDelegata. Dodajte sledei kod u Class1.cs:

26

Pokrenite program.

27

Kako to radi
Ovaj kod definie delegat (procesDelegati) iji se potpis slae sa dve funkcije (Pomnozi() i
Podeli()). Definicija delegata je sledea:
delegate double procesDelegati(double param1, double param1);
Kljuna re delegate ukazuje na to da se definicija odnosi na delegata, a ne na funkciju
(definicija se nalazi na istom mestu gde bi stajala i definicija funkcije). Zatim imamo potpis
koji definie povratnu vrednost tipa double, i dva parametra tipa double. Stvarna imena koja
se koriste nisu bitna, tako da moemo nazvati tip delegata i ime parametra kako god elimo.
Ovde smo delegat nazvali procesDelegati, a parametre param1 i param2.
Kod u funkciji Main() poinje deklaracijom promenljive koja koristi novi tip delegata:

Zatim imamo standardan C# kod koji trai dva broja odvojena zarezima i smeta ove brojeve u
dve promenljive tipa double:

Primetiete daje ovde zbog demonstracije izostavljena provera ispravnosti unosa korisnika.
Da se radi o pravom" kodu, proveli bismo jo vremena proveravajui da lije korisnik uneo
vrednosti u okvirima potrebnim za normalno izvrenje programa.
Zatim pitamo korisnika da li eli da se ovi brojevi pomnoe ili podele:

Na osnovu korisnikov izbora, inicijalizujemo promenljivu delegata process.

28

Da bismo dodelili referencu na funkciju promenljivoj delegata, koristimo malo udnu sintaksu.
Kao kod dodeljivanja vrednosti nizova, moramo koristiti kljunu re new da napravimo novog
delegata.
Posle te kljune rei navodimo tip delegata i obezbeujemo parametar koji se odnosi na
funkciju koju elimo da koristimo, uglavnom Console.WriteLine(). Upamtite da se ovaj
parametar ne slae sa parametrom tipa delegata ili ciljnom funkcijom - ovo je jedinstvena
sintaksa pri dodeljivanju delegata. Parametar je jednostavno ime funkcije koja se koristi, bez
ikakvih zagrada.
Na kraju pozivamo izabranu funkciju koristei delegat. Ovde ista sintaksa radi posao bez
obzira na koju se funkciju odnosi delegat:

Naravno unosimo i kod jedne i kod druge pitalice.


Na kraju obezbeujemo se kad korisnik nije izabrao ni jednu od ponuenih opcija.

U programu, se promenljiva delegata tretira kao ime funkcije. Za razliku od funkcija, sa ovom
promenljivom se mogu izvesti dodatne operacije, kao to je njeno prosleivanje drugoj
funkciji preko parametara. Jednostavan primer ovakve funkcije bio bi:
static void executeFunction(procesDelegati process)
{
process(2.2, 3.3);
}
To znai da ponaanje funkcije moemo kontrolisati prosleujui joj delegate, nalik na
korienje dopunskih modula. Na primer, moemo imati funkciju koja sortira niz tipa string po
azbunom redu.
Postoji nekoliko metoda sortiranja lista sa razliitim performansama, u zavisnosti od
karakteristika lista koje se sortiraju. Korienjem delegata moemo navesti metod koji e se
koristiti, prosleujui delegat koji pokazuje na funkciju sa algoritmom za sortiranje, funkciji
koja obavlja sortiranje.
Postoji mnogo ovakvih primena delegata, ali je njihova najbolja primena kod obrade
dogaaja.

29

Saetak
U ovom predavanju smo videli kompletan pregled korienja funkcija u C# kodu. Mnoge od
dodatnih osobina koje funkcije nude (posebno delegati) vie su apstraktne i o njima emo
govoriti tek u svetlu objektno orijentisanog programiranja, o emu e uskoro biti rei.
Saetak svega to smo preli u ovom predavanju:
Definisanje i korienje funkcija u konzolnim aplikacijama
Razmena podataka sa funkcijama kroz povratne vrednosti i parametre
Nizovi parametara
Prosleivanje vrednosti preko referenci ili preko vrednosti
Navoenje izlaznih parametara za dodatne povratne vrednosti
Koncept opsega vaenja promenljivih
Detalji o funkciji Main(), ukljuujui upotrebu parametra komandne linije
Korienje funkcija u strukturama
Preoptereenje funkcija
Delegati

Vebe
1. Sledee dve funkcije imaju greke. Koje su to greke?
static bool Write()
{
Console.WriteLine(Izlazni tekst funkcije.);
}
static void mojaFunkcija(string label, params int[] args, bool prikaziLabel)
{
if (prikaziLabel)
Console.WriteLine(label);
foreach (int i in args)
Console.WriteLine({0} , i)
}
2. Napiite aplikaciju koja koristi dva argumenta komandne linije, tako da smesti vrednosti u
promenljive tipa string ili tipa int. Zatim prikaite ove vrednosti.
3. Napravite delegat i koristite ga da oponaa funkciju Console. ReadLine() kada se trai
korisnikov unos.
4. Prepravite sledeu strukturu tako da ukljuuje funkciju koja vraa ukupnu cenu za
poradbinu:
struct porudzbina
{
public int brojPorudzbine
public string imeArtikla
public double vredPorudzbine
}
30

5. Dodajte jo jednu funkciju strukturi porudzbina koja vraa formatiran string na sledei
nain: svi unosi koji su u kurzivu i uokvireni u ugaone zagrade moraju se zameniti
odgovarajuim vrednostima.

31

Dogaaji
Ovo je poslednje poglavlje OOP sekcije ove knjige, u kojem opisujemo jednu od najee
korienih OOP tehnika u .NET-u: dogaaje.
Kao i uvek, poeemo od osnovnih stvari i prodiskutovati o tome ta su to zaista dogaaji.
Posle toga, pogledaemo primere jednostavnih dogaaja i ta se sve s njima moe uraditi.
Kada zavrimo sa tim, videemo kako da kreiramo i koristimo sopstvene dogaaje.
Dakle, pogledajmo ta su to dogaaji.

ta je dogaaj?

Dogaaji su slini izuzecima u tome to su aktivirani od strane objekata, a mi moemo


obezbediti kod koji reaguje na njih. Meutim, postoje i neke razlike. Jedna od najvanijih
jeste ta da nema ekvivalentne try. . . catch strukture za obradu dogaaja. Umesto toga,
moramo se prijaviti na dogaaj. Prijavljivanje na dogaaj podrazumeva pisanje koda koji e se
izvriti kada je dogaaj aktiviran, u obliku rutine za obradu dogaaja.
Dogaaj moe imati vise ratina za obradu dogaaja, koje e sve biti pozvane kada je dogaaj
aktiviran. Rutine za obradu dogaaja mogu biti deo iste klase kojoj pripada objekat koji
aktivira dogaaj, a mogu pripadati i nekim drugim klasama.
Rutine za obradu dogaaja su jednostavne funkcije. Jedina restrikcija za ove funkcije jeste ta
da se potpis (tip podatka koji se vraa, i parametri) mora podudarati sa onim to zahteva
dogaaj. Ovaj potpis je deo definicije dogaaja, odreen od strane delegata.
Upravo zato to se koristi u dogaajima, delegat je mono oruje. To je razlog to smo im
posvetili neto vie vremena predavanju o funkcijama. Moda biste hteli ponovo da proitate
ovu sekciju, da se podsetite ta je to delegat i kako se koristi.
Sekvenca obrade izgleda ovako:
Prvo - aplikacija kreira objekat koji moe aktivirati dogaaj. Na primer, neka je aplikacija
zaduena za instant poruke, i objekat koji ona kreira predstavlja vezu sa udaljenim korisnikom.
Objekat veze moe aktivirati dogaaj, npr. kada stigne poruka od udaljenog korisnika.

Sledee - aplikacija se prijavljuje na dogaaj. Ovo bismo mogli postii definisanjem funkcije
koja bi se koristila sa delegat tipom koji je odredio dogaaj, i koja bi imala parametar referencu na dogaaj. Rutina za obradu dogaaja moe biti metoda na nekom drugom objektu.
Neka to bude, npr. objekat koji predstavlja ureaj za prikaz instant poruke.

Kada je dogaaj aktiviran, aplikacija je obavetena. Kada stigne instant poruka kroz objekat
veze, bide pozvana rutina za obradu dogaaja na ureaju za prikaz. Poto koristimo
standardnu metodu, objekat koji aktivira dogaaj moe proslediti, kroz parametre, bilo koju
relevantnu informaciju pravei tako raznovrsne dogaaje. U naem sluaju, jedan parametar
moe biti tekst iz instant poruke. Ovaj tekst moe se prikazati pomou ratine za obradu
dogaaja na ureaju za prikaz.

Korienje dogaaja

U ovoj sekciji pogledaemo kod ratine za obradu dogaaja, a zatim emo videti kako moemo
definisati i koristiti na sopstveni kod.
Obrada dogaaja
to smo ve rekli, za obradu dogaaja neophodno je prijaviti dogaaj, to znai obezbediti
ratinu za obradu dogaaja iji se potpis podudara sa delegatom koji koristi dogaaj.
Pogledajmo primer koji koristi jednostavan objekat Timer koji aktivira dogaaj, posle ega e
biti pozvana rutina za obradu dogaaja.

Primer obrade dogaaja

Veba br. 18.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Console Application u okviru prozora Templates: (za ovo ete morati malo da pomerite
prozor
na
dole).
U
okviru
za
tekst
Location:
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba18 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: Dogadjaji1
Dodajte sledei kod u Class1.cs:

Kako to radi

Objekat koji koristimo za aktiviranje dogaaja je instanca klase System.Timers.Timer. Ovaj


objekat je inicijalizovan vremenskim periodom (u milisekundama). Kada se objekat Timer
startuje korienjem metode Start(), aktiviran je niz dogaaja razdvojenih vremenskim
periodom koji je odreen. Funkcija Main() inicijalizuje objekat Timer vremenskim periodom od
100 milisekundi, tako da e aktivirati 10 dogaaja u sekundi:

Objakat Timer ima dogaaj koji se zove Elipsed. Moemo ga videti ako koristimo prozor Object
Broser:

Potpis rutine za obradu ovog dogaaja definisan je u tipu delegata System.Timers.ElapsedEventHandler, koji je jedan od standardnih delegata definisanih u .NET okruenju. Ovaj
delegat se koristi za funkcije koje se podudaraju sa sledeim potpisom:
void functionName(object source, ElapsedEventArgs e);

Objekat Timer alje referencu na samog sebe, u prvom parametra, i instancu ElapsedEventArgs
klase u drugom parametru. Za sada moemo ignorisati ove parametre, ali pogledaemo ih
kasnije.
U kodu imamo funkciju koja se podudara sa ovim potpisom:

Ova metoda koristi dva statika polja klase Class1, brojac i displayString, za prikaz jednog
znaka. Za svaki sledei poziv metode, znak koji se prikazuje bie razliit.

Poslednje to moramo obaviti jeste da poveemo dogaaj i rutina za obradu dogaaja - da ga


prijavimo. To postiemo operatorom += dodajui dogaaj rutinu za obradu dogaaja, u formi
nove instance delegate inicijalizovane naom ratinom za obradu dogaaja:

Ova komanda (koja koristi malo udnu sintaksu, svojstvenu delegatima) dodaje rutinu za
obradu dogaaja u listu koja e biti pozvana kada se aktivira dogaaj Elapsed. Moemo dodati
koliko god hoemo rutina za obradu dogaaja u ovu listu, dokle god one zadovoljavaju
postavljene kriterijume. Sve ratine za obradu dogaaja e biti pozvane kada se dogaaj
aktivira.
Sve to ostaje funkciji Main() jeste da pokrene Timer:

Poto ne elimo da okonamo aplikaciju pre nego to obradimo bilo koji dogaaj, stavljamo
funkciju Main() na ekanje. Najlaki nain da ovo postignemo jeste kroz zahtev za unos podataka od strane korisnika, jer se obrada nee zavriti dok korisnik ne unese red teksta i/ili
pritisne Enter.

Iako se obrada u funkciji Main() zavrava ovde, obrada u objektu Timer se nastavlja. Kada ovaj
objekat aktivira dogaaje, poziva se metoda WriteChar() koja se istovremeno izvrava sa
Console.ReadLine() iskazom.

Definisanje dogaaja

Pogledajmo kako da definiemo i koristimo nae sopstvene dogaaje. Implementiraemo


verziju primera za instant poruke sa poetka ovog poglavlja. Kreiraemo objekat Konekcija
koji aktivira dogaaje obraene od strane objekta Display.
Primer definisanja dogaaja

Veba br. 19.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Console Application u okviru prozora Templates: (za ovo ete morati malo da pomerite
prozor
na
dole).
U
okviru
za
tekst
Location:
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba19 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: Dogadjaji2
Dodajte sledei kod u Class1.cs:
Dodajte novu klasu Konekcija u Konekcija.cs:

Dodajte novu klasu Display u Display.cs:

Izmenite kodu Class1.cs:

Pokrenite aplikaciju.

Kako to radi

Najvei posao u ovoj aplikaciji obavlja klasa Konekcija. Instance ove klase koriste objekte
Timer, kao to smo videli u prvom primeru ovog poglavlja, inicijalizujui ih u konstruktoru
klase. Takoe, obezbeuju pristup statusu objekta Timer (omoguiti ili onemoguiti) kroz
metode Connect() i Disconnect():

Takoe, u konstruktoru prijavljujemo rutinu za obradu dogaaja za Elapsed dogaaj, kao to


smo to radili u prvom primeru. Metoda CheckForMessage() aktivira dogaaj, u proseku jednom
od svakih deset puta kada je pozvana. Pre nego to predemo na kod za ovu metodu,
pogledajmo definiciju samog dogaaja.
Pre nego to definiemo metodu, moramo definisati tip delegata koji se koristi sa dogaajem,
tj. tip delegata koji odreuje potpis koji mora imati i rutina za obradu dogaaja. To radimo uz
pomo standardne sintakse za delegate - definiemo ga kao javni tip unutar imenovanog
prostora Dogadjaji2, da bi bio dostupan spoljanjem kodu:

Ovaj tip delegata, koji smo nazvali MessageHandler, jeste potpis za void funkcije koje imaju
jedan string parametar. Taj parametar moemo koristiti za prenos instant poruke primljene od
objekta Konekcija do objekta Display.
Kada je delegat definisan (ili je odgovarajui postojei delegat lociran), moemo definisati i
sam dogaaj kao lan klase Konekcija:

Jednostavno imenujemo dogaaj (ovde smo koristili ime MessageArrived) i deklariemo ga,
koristei kljunu re event i tip delegata (tip delegate MessageHandler koji smo ve
definisali). Kada je dogaaj deklarisan na ovaj nain, moemo ga aktivirati pozivajui ga po
imenu, kao da se radi o metodu sa potpisom odreenim od strane delegata. Na primer,
moemo aktivirati dogaaj na sledei nain:

:
Da je delegat definisan bez parametara, mogli smo napisati:
MessageArrived();

Mogli smo definisati i vise od jednog parametra, koji bi zahtevali vise koda za aktiviranje
dogaaja. Naa metoda ProveraPoruke() izgleda ovako:

Koristimo instancu klase Random koju smo videli ranije, za sluajan izbor broja izmeu 0 i 9,
kao i za aktiviranje dogaaja ukoliko je izabrani broj 0, to e se desiti u 10% sluajeva. Ovo
simulira ispitivanje veze radi provere da li je poruka stigla, to nee biti sluaj svaki put kada
proveravamo.
Skreemo panju da dogaaj aktiviramo samo ako je izraz MessageArrived ! = null taan. Ovaj
izraz, koji koristi sintaksu delegata na neuobiajen nain, u stvari znai: Da li uopte postoji
neto to bi aktiviralo dogaaj?" Ako tako neto ne postoji, MessageArrived e uzeti vrednost
null, tako da nema nikakvog smisla aktivirati dogaaj.

Klasa koja e reagovati kada je dogaaj aktiviran jeste klasa Display. Ona sadri jednu metodu
DisplayMessage():

Ova metoda ima odgovarajui potpis (i javna je, to je obavezno za ratine za obradu dogaaja
koji ne pripadaju istoj klasi, kao i za objekat koji aktivira dogaaj), tako da je moemo
koristiti za obradu dogaaja MessageArrived.
Sve to preostaje da se uradi u funkciji Main() jeste inicijalizacija dve instance klasa
Konekcija i Display, i njihovo povezivanje. Kod je slian onome iz prvog primera:

Ponovo pozivamo metod Console.ReadLine() da pauzira obradu u funkciji Main() kada


predemo na metodu Connect() objekta Konekcija.

Vienamenske rutine za obradu dogaaja


Potpis koji smo videli ranije za dogaaj Timer.Elapsed, sadri dva parametra iji se tipovi
esto sreu u rutinama za obradu dogaaja. Ti parametri su:
object source - referenca na objekat koji aktivira dogaaj.
ElapsedEventArgs e - parametri koje alje dogaaj.
Razlog zbog kojeg koristimo parametar tipa object za ovaj dogaaj, kao i za mnoge druge
dogaaje, jeste taj to emo esto hteti da koristimo jednu rutinu za obradu dogaaja za vise
identinih dogaaja aktiviranih od strane razliitih objekata. Na ovaj nain moemo tano
znati koji objekat aktivira dogaaj.

10

Proirimo malo poslednji primer.

Veba br. 20.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Console Application u okviru prozora Templates: (za ovo ete morati malo da pomerite
prozor
na
dole).
U
okviru
za
tekst
Location:
promenite
putanju
u
C:\Temp\SoftIng\LecturesCode\Vezba20 (ovaj e direktorijum biti automatski napravljen
ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name: Dogadjaji3
Dodajte sledei kod u Class1.cs:
Kopirajte kod iz Class1.cs, Konekcija.cs i Display.cs iz projekta Dogadjaji2. Vodite rauna da
promenite imenovani prostor iz Dogadjaji2u Dogadjaji3.
Dodajte novu klasu, MessageArrivedEventArgs, u datoteku MessageArrivedEventArgs.cs:
using System; namespace Dogadjaji3

Izmenite Connection.cs:

11

Izmenite Display.cs:

12

Izmenite Class1.cs:

Pokrenite aplikaciju:

13

Kako to radi
Slanjem reference na objekat koji aktivira dogaaj kao jednog od parametra ratine za obradu
dogaaja, moemo prilagoditi odgovor ratine na individualni objekat. Referenca daje pristup
izvornom objektu, ukljuujui i njegova svojstva.
Slanjem parametara koji su sadrani u klasi izvedenoj iz System.EventArgs (kao to je
ElapsedEventArgs), moemo obezbediti bilo koje dodatne informacije koje su neophodne kao
parametre (npr. parametar Poruka nae MessageArrivedEventArgs klase).
Polimorfizam e dodatno koristiti parametrima. Mogli bismo definisati ratinu za obradu
dogaaja MessageArrived:

Izmenite definiciju delegata u datoteci Kolekcija.cs:

Aplikacija e se izvravati kao i pre, s tim da je funkcija DisplayMessage() mnogostrana (bar


teoretski - dodatna implementacija bi bila neophodna za kvalitetan proizvod). Ista rutina moe
raditi i sa dragim dogaajima, kao to je dogaaj Timer.Elapsed. U tom sluaju, morali bismo
izmeniti rutinu tako da parametri koji se alju kada je dogaaj aktiviran budu valjano obraeni
(konverzija parametara u objekte Konekcija i MessageArrivedEventArgs na ovaj nain izazvala
bi izuzetak; trebalo bi koristiti operator as).
Pre nego to krenemo dalje, primetite da se dogaaji aktiviraju u parovima, zbog dva objekta
Konekcija. U pitanju je nain na koji klasa Random generie sluajne brojeve. Kada se kreira
objekat Random, koristi se poetna vrednost. Ova poetna vrednost koristi kompleksnu

14

jednainu za generisanje niza pseudosluajnih brojeva. (Raunari nisu u stanju da generiu


prave sluajne brojeve.) Poetnu vrednost za Random objekat moemo definisati u
konstruktora, ali ako to ne uradimo (kao to i nismo), trenutno vreme se koristi kao poetna
vrednost. Poto formiramo dva Connection objekta u dva reda koda, koji idu jedan za dragim,
postoji velika verovatnoa da e se koristiti iste poetne vrednosti kada objekti odgovaraju na
dogaaj Timer.Elapsed. Ako jedan objekat generie poruku, vrlo je verovatno da e i dragi to
initi, to je posledica brzine obrade. Da bismo reili problem, moramo drugaije podesiti
poetne vrednosti. Jedno reenje, koje ovde neemo raditi, bilo bi da se obezbedi instanca
klase Random kojoj se moe pristupiti iz oba objekta Konekcija. Objekti bi, u tom sluaju,
koristili isti niz sluajnih brojeva, to bi bitno umanjilo ansu za prikazivanje sinhronizovanih
poruka.

Povratne vrednosti i rutina za obradu dogaaja


Svi moduli koje smo do sada videli imali su povratni tip void. Mogue je obezbediti neki dragi
tip, ali to dovodi do problema zato to neki dogaaj moe imati za posledicu pozivanje
nekoliko rutina za obradu dogaaja. Ako sve ove ratine vrate neku vrednost, postaje nejasno
koju od vrednosti uzimamo.
Sistem reava problem tako to mm dozvoljava pristup samo poslednjoj vraenoj vrednosti.
Ovo je vrednost koju vraa poslednja ratina za obradu dogaaja koja se odnosi na neki
dogaaj.
Moda ovo reenje ima upotrebnu vrednost u nekoj situaciji, ali ipak preporuujemo korienje
povratnog tipa void za ratine za obradu dogaaja, kao i izbegavanje korienja parametara
tipa out.

15

Korienje dijaloga u C #
U prethodnim predavanjima videli smo kako da implementiramo menije, palete sa alatkama,
SDI i MDI formulare i sl. Ve znamo kako da prikaemo jednostavne okvire za poruke i da
dobijemo informacije od korisnika. Napravili smo prefinjenije posebne dijaloge da upitaju
korisnika za posebne informacije. Ipak, ako je mogue, trebalo bi da koristite preddefinisane
dijaloge klase, pre nego posebne dijaloge za obine operacije kao to su otvaranje i snimanje
datoteka ili tampanje. Ovo nije samo prednost ostvarivanja zadatka sa manje koda, ve i
korienja standardnih poznatih Windows dijaloga. .NET okruenje sadri klase koje se kae na
Windows dijaloge za otvaranje i snimanje datoteka, za pristupanje tampaima, kao i za
biranje boja i fontova. Mogunost korienja tih dijaloga umesto posebnih dijaloga znai da nije
neophodno za korisnika da naui kompleksnu metodologiju koja bi bila potrebna da bi se takva
funkcionalnost napravila iz poetka.
U ovom predavanju nauiemo kako se koriste ove klase sa standardnim dijalozima. Konkretno:
Videemo kako se koriste klase OpenFileDialog i SaveFileDialog.
Nauiemo hijerarhiju klasa za tampanje u .NET-u, i pomou klasa PrintDialog,
PageSetupDialog i PrintPreviewDialog implementiraemo tampanje i pregled pre
tampanja.
Upoznaemo klase FontDialog i ColorDialog kako bismo menjali fontove i boje.

Dijalozi
Dijalog je prozor koji je prikazan u sadrini konteksta drugog prozora. Moemo da upitamo
korisnika za unos podataka pre nego to nastavimo tok naeg programa. Opti dijalog je dijalog
koji se esto koristi da se dobiju potrebne informacije od korisnika, i deo je Windows
operativnog sistema.
Sa .NET radnim okruenjem imamo sledee klase dijaloga:

Sve ove klase dijaloga, izuzev PrintPreviewDialog, izvedene su iz apstraktne klase


CommonDialog koja ima metode da upravlja Windowsovim optim dijalogom.
Klasa CommonDialog definie sledee metode i dogaaje, zajednike za sve opte klase
dijaloga:
Metodi i dogaaji javne
instance
ShowDialog()
Reset()
HelpRequest

Opis
Ova metoda je implementirana iz izvedene klase da
prikae opti dijalog.
Svaka izvedena klasa dijaloga implementira metodu
Reset()
da postavi sva svojstva klase dijaloga na
njihove podrazumevane vrednosti.
Ovaj dogaaj se pojavljuje kada korisnik pritisne
dugme Help na optem dijalogu.

Sve ove klase dijaloga obmotavaju opti Windows dijalog da bi napravile dijalog dostupan za
.NET aplikacije. Klasa PrintPreviewDialog je izuzetak, jer dodaje sopstvene elemente u
Windows formular da kontrolie pregled tampanja i nije zapravo dijalog. Klase OpenFileDialog
i SaveFileDialog nastale su iz apstraktne bazne klase FileDialog koja dodaje mogunosti rada sa
datotekama, koje su zajednike za otvaranje i zatvaranje datoteke.
Pregledajmo gde se sve mogu koristiti razliiti dijalozi:
Da bi korisnik izabrao i pregledao datoteke za otvaranje koristi OpenFileDialog. Ovaj
dijalog moe se konfigurisati tako da se samo jedna datoteka ili viestruke datoteke
mogu izabrati.
Sa dijalogom SaveFileDialog korisnik moe da odabere ime
direktorijum u kome se jedna datoteka ili vie njih mogu izabrati.

datoteke i potrai

PrintDialog se koristi da se izabere tampa i postave opcije za tampu.


Da bi se konfigurisale margine strane, uglavnom se koristi PageSetupDialog.
PrintPreviewDialog je jedan nain da se uradi pregled pre tampe na ekranu sa nekoliko
opcija (npr. zumiranje).
FontDialog
izlistava sve instalirane Windows fontove sa stilovima, veliinama i
pregledom da se izabere eljeni font.
Klasa ColorDialog olakava izbor boje.
Kod nekih aplikacija razvijenih od iste kompanije ne samo da nisu opti dijalozi korieni, ve
ni stil za pravljenje posebnih dijaloga nije bio korien. Razvoj ovih dijaloga dao je
funkcionalnost koja nije bila postojana, gde su se neka dugmad i okviri sa listom nalazili na
drugim mestima, na primer OK i Cancel dugme su bili okrenuti.
Ponekad se ta nepostojanost moe nai i unutar jedne aplikacije. To je frustrirajue za
korisnika i poveava vreme za zavravanje zadatka.
Budite postojani u dijalozima koje pravite i koristite! Postojanost moe lako da se postigne
korienjem optih dijaloga. Opti dijalozi se koriste od raznih aplikacija ve poznatih
korisniku.

Kako se koriste dijalozi


Poto je klasa CommonDialog osnovna klasa za sve klase dijaloga, tako se sve klase dijaloga
slino koriste. Javne metode instance su ShowDialog() i Reset(). Metoda ShowDialog poziva

zatieni RunDialog metod instance da prikae dijalog i konano vraa instancu DialogResult sa
informacijom o tome kakvu je korisnik interakciju vrio sa dijalogom. Metod Reset() zapravo
postavlja svojstva klase dijaloga na njihove podrazumevane vrednosti.
Sledei segment koda pokazuje primer kako se klasa dijaloga moe koristiti. Kasnije,
pogledaemo detaljnije na svaki od ovih koraka; prvo da uvedemo koncept kako e se dijalozi
koristiti.
Kao to moete videti u sledeem segmentu koda:
Prvo se pravi nova instanca klase dijaloga.
Zatim moramo da postavimo neka svojstva da ukljue/iskljue opcionalne mogunosti i
postave stanje dijaloga. U ovom sluaju, postaviemo svojstvo Title na Primer, i
postaviemo fleg ShowReadOnly na true.
Pozivajui metod ShowDialog(), dijalog se prikazuje, eka i reaguje na korisniki unos.
Ako korisnik pritisne dugme OK - dijalog se zatvara. Proveravamo pritisak na OK
poredei rezultat dijaloga sa DialogResult. OK. Posle toga, moemo uzeti vrednosti iz
korisnikog unosa ispitujui odreene vrednosti svojstava. U ovom sluaju, uvamo
vrednost svojstva FileName u promenljivoj FileName:

Naravno, svaki dijalog ima sopstvene opcije za podeavanje, koje traimo u sledeim
sekcijama.
Ako koristite dijalog u aplikacijama sa Windows formularima, to je ak i lake od nekoliko
redova koda. Dizajner Windows formulara pravi kod za kreiranje nove instance i postavljanje
vrednosti svojstava. Mi jednostavno moramo da pozovemo metod ShowDialog() i doemo do
promenjenih vrednosti, kao to emo videti.

Dijalozi za rad sa datotekama


Dijalogom za rad sa datotekama korisnik moe da odabere disk i pretrauje kroz sistem
datoteka da bi izabrao datoteku. Sve to elimo da imamo od korisnika jeste ime datoteke.
Sa dijalogom OpenFileDialog moemo da izaberemo ime za datoteku koju elimo da otvorimo,
a korienjem dijaloga SaveFileDialog moemo navesti ime datoteke koju elimo da snimimo.
Ove klase dijaloga su vrlo sline jer su izvedene iz iste apstraktne osnovne klase, iako postoje
svojstva jedinstvena za svaku klasu. U ovoj sekciji prvo emo pogledati karakteristike klase
OpenFileDialog, a tada emo pogledati gde se klasa SaveFileDialog razlikuje. Razviemo
primer aplikacije koja koristi i jednu i drugu klasu.

Klasa OpenFileDialog
Klasa OpenFileDialog nam omoguava da izaberemo datoteku za otvaranje. Kao to smo videli u
naem primeru iznad, nova instanca klase OpenFileDialog se pravi pre nego to se pozove
metod ShowDialog().

Pokretanje programa sa ova dva reda koda e rezultovati ovim dijalogom:

Kao to smo ve videli, moemo postaviti svojstva ove klase pre poziva metoda ShowDialog(),
to menja ponaanje i izgled ovog dijaloga, ili ograniava datoteke koje se mogu otvoriti. U
sledeoj sekciji, pogledaemo mogue ispravke.
Kada
koristimo
klasu
OpenFileDialog
sa
konzolnim
aplikacijama,
sklop
System.Windows.Forms mora da bude u referencama, a imenovani prostor
System.Windows.Forms mora biti uvren. Sa Windows Forms aplikacijama pisanim u Visual
Studio .NET-u, ovo je ve uinjeno iz arobnjaka za kreiranje aplikacije.

Naslov dijaloga
Podrazumevani naslov za dijalog OpenFileDialog je Open. Moete promeniti naslov dijaloga
postavljanjem svojstva Title. Open nije uvek najbolje ime ako, na primer, u aplikaciji elite da
analizirate dnevnike datoteke da biste proverili neke informacije i da izvrite proraune na
njima, ili dobijete veliine datoteka, i posle celokupne obrade koja je potrebna zatvarate
datoteke. U ovom sluaju, datoteke ne ostaju dugo otvorene za korisnika, tako da bi naslov
Analiza Datoteka bolje pristajao. Sam Visual Studio .NET ima razliite naslove za dijaloge za
otvaranje datoteka da bi razlikovao tip podataka koji je otvoren: Open project, Open File,
Open Solution i Open File from Web.
Ovaj segment koda pokazuje kako se mogu podeavati razliiti naslovi.

Navoenje direktorijuma
Podrazumevano, dijalog otvara direktorijum koji je otvoren od strane korisnika kada su zadnji
put pokretali aplikaciju, i prikazuje datoteke u tom direktorijumu. Postavljanjem svojstva
InitialDirectory, menja se ovo ponaanje. Podrazumevana vrednost svojstva Initial-Directory je
prazan string koji predstavlja korisnikov direktorijum My Documents, i prikazan je prvi put
kada je pokrenuta aplikacija. Drugi put kada se dijalog otvori, prikazani direktorijum bie isti
onaj kao i za prethodno otvaranu datoteku. Opti Windows dijalog koji poziva OpenFileDialog
koristi registracionu bazu da locira ime prethodno otvarane datoteke.

Moete promeniti ovo ponaanje postavljajui svojstvo InitialDirectory na putanju


direktorijuma pre poziva metoda ShowDialog(). Nikad ne bi trebalo da koristite fiksni string
direktorijuma jer isti ne mora da postoji i na korisnikovom sistemu. Da dobijete specijalne
sistemske direktorijume moete da koristite statiki metod GetFolderPath() klase System.
Environment. Metod GetFolderPath() prihvata enumeraciju Environment.SpecialFolder, gde
moete definisati za koji sistemski direktorijum elite da vam se vrati putanja.
U sledeem primeru koda, koristimo opti korisniki direktorijum za ablone da ga postavimo
kao InitialDirectory:

Postavljanje filtera za datoteke


Ovaj filter definie tipove datoteka koje korisnik moe izabrati da otvori. Jednostavan filter
string moe da izgleda ovako:
Text Documents (*.txt | *.txt|All Files | *.*

Ovaj filter se koristi da prikae ulaze u okviru sa listom Files of type. Microsoft WordPad
prikazuje ove ulaze:

Filter ima viestruke segmente koji su odvojeni znakom I .Dva stringa uvek pripadaju zajedno,
tako da broj segmenata uvek treba da bude paran broj. Prvi string definie tekst koji e biti
prikazan u okviru sa listom; drugi string se koristi da naglasi oznake za tip datoteka koje e
prikazati u dijalogu. Postavljamo filter string sa svojstvom Filter, kao to se moe videti u kodu
ispod:

Postavljanje pogrene vrednosti Filter rezultuje izuzetkom u vreme izvravanja,


System.ArgumentException, sa sledeom porukom o greci: The provided filter string is
invalid. Prazno mesto pre ili posle filtera takoe nije dozvoljeno.
Svojstvo FilterIndex definie podrazumevani izbor u okviru sa listom. Sa WordPadom
podrazumevan je Rich Text Format (*.rtf) kao to je naglaeno u slici iznad, to moe biti
teko za itanje ali vidi se kada se otvori WordPad. Ako imate viestruke tipove datoteka iz
kojih treba da birate, onda moete podesiti FilterIndex na podrazumevani tip datoteka.
Obratite panju da FilterIndex ima za osnovu 1.

Validacija
Klasa OpenFileDialog moe da radi neto automatske validacije datoteke pre nego to pokuate
da je otvorite. Sa ValidateNames, ime datoteke se proverava da se vidi da li je ispravno

Windows ime. Pritiskanje dugmeta OK sa neispravnim imenom izbacuje sledei dijalog, i


korisnik ne moe da napusti OpenFileDialog pre nego to ispravi ime datoteke. Neispravno ime
sadri neispravne znake kao to su \\, /, ili: i.
Unoenje neispravnog imena ttt\\ttt rezultuje sledeom porukom o greci:

CheckFileExists i CheckPathExists su dodatna svojstva za validaciju. Sa CheckPathExists


proverava se putanja, a CheckFileExists - datoteka. Ako datoteka ne postoji, sledei dijalog se
pokazuje kada se pritisne dugme OK:

Podrazumevano za ova tri svojstva je true, tako da se validacija deava automatski.

Pomo
Klasa OpenFileDialog podrava dugme za pomo koje je podrazumevano nevidljivo.
Podeavanje svojstva ShowHelp na true ini ovo dugme vidljivim, i moete dodati rutinu za
obradu dogaaja HelpRequest da prikae pomo korisniku.

Rezultati
Metoda ShowDialog() klase OpenFileDialog vraa enumeraciju DialogResult. Enumeracija
DialogResult definie lanove Abort, Cancel, Ignore, No, None, OK, Retry i Yes. None je
podrazumevana vrednost koja se postavlja sve dok korisnik ne zatvori dijalog. U zavisnosti od
pritisnutog dugmeta, odgovarajui rezultat se vraa. Sa klasom OpenFileDialog, vraaju se
samo DialogResult. OK i DialogResult. Cancel.
Ako je korisnik pritisnuo dugme OK, izabranom imenu datoteke moe da se pristupi koristei
svojstvo FileName. Ako je korisnik ponitio dijalog, FileName je samo prazan string. Ako je
svojstvo MultiSelect postavljeno na true tako da korisnik moe da izabere vise od jedne
datoteke, dobijate sva imena datoteka pristupom svojstvu FileNames, koje vraa niz stringova.
Ovaj mali deo koda pokazuje kako viestruka imena datoteka mogu da budu dobijena iz dijaloga
OpenFileDialog:

Metod ShowDialog() otvara dijalog. Svojstvo Multiselect je postavljeno na true, korisnik moe
da bira viestruke datoteke. Pritiskom na dugme OK dijaloga isti se zavrava, ako sve prode
dobro i DialogResult. OK bude vraen. Sa foreach iskazom, prolazimo kroz sve stringove u nizu
stringova koji su vraeni u svojstvu FileNames i prikazujemo svaku izabranu datoteku.

Svojstva klase OpenFileDialog


U sledeoj slici moemo da vidimo klasu OpenFileDialog sa svim moguim svojstvima koja
omoguuju ukljuivanje elemenata prozora. Na slici lako moete da vidite koja svojstva utiu
na koje elemente korisnikog interfejsa:

Veba br. 21.


Kreiranje Windows aplikacije
1. Da bismo se oprobali na otvaranju i zatvaranju datoteka, napraviemo jednostavnu Windows
aplikaciju ProstiEditor:

2. Promenite generisanu datoteku Form1.cs u ProstaForma.cs i klasu Form1 u frmMain.


Takoe, menjamo imenovani prostor u Prosti.Editor.
Kada se menja ime klase, takoe morate promeniti implementaciju metode Main() tako da
odraava promenu u imenu, jer se ovo ne radi automatski postavljanjem svojstva Name klase
Form:

3. Promenite svojstvo Text formulara u Prosti Editor. Okvir za unos teksta sa vise redova e biti
povrina za itanje i menjanje podataka iz datoteke, tako da dodajete kontrolu TextBox iz
okvira sa alatima u dizajneru Windows formulara. Okvir sa tekstom treba da ima vise redova i
trebalo bi da prekriva celu povrinu aplikacije, prema tome postavite sledea svojstva na
odreene vrednosti.

Osobina (Properties)
(Name)
Text
Multiline
Dock
ScrollBars
AceeptsReturn
AcceptsTab

Vrednost (Value)
txtBoxEdit
<empty>
True
Fill
Both
True
True

4. Sledee, potrebna nam je kontrola MainMenu za aplikaciju.


Glavni meni treba da ima ulaz File sa podmenijima New, Open,
Save i Save As, kako se vidi na sledeoj slici:
Da bi kod bio itljiviji, promenite imena u vrednosti u sledeoj
tablici. Svojstvo Text je prikazano u meniju. & znak odreuje da e
sledei znak biti podvuen, ako se tastatura koristi za pristup
meniju pomou tastera <ALT> i podvuenog znaka. Znak . . . u
svojstvu Text Open i Save As ulaza menija znai da e korisnik biti
upitan za podatke pre nego to se akcija dogodi - dijalog e biti
otvoren. Kada birate menije File, New i Save, akcija se dogaa bez
dodatne intervencije.
Da se ukratko podsetimo kako moete dodati podulaze menija. im upiete tekst &File u ulazu
glavnog menija, podmeni se otvara ispod njega, u kojem moete da upisujete podulaze u okvir
Type Here.
Ime stavke menija
miFile
miFileNew
miFileOpen
miFileSave
miFlleSaveAs

Text
&File
&New
&Open...
&Save
Save &As...

5. Rutina za ulaz glavnog menija &New treba da obrise podatke iz okvira za tekst pozivom
metode Clear() kontrole TextBox:

6. Takoe, promenljiva lanica fileName treba da bude postavljena na Untitled. Moramo da


deklariemo i inicijalizujemo ovu promenljivu lanicu u klasi frmMain:

U meniju Open elimo da prikaemo dijalog za otvaranje datoteka, sto emo sledee i uraditi.

itanje datoteke
Sa Prostim Editorom trebalo bi da je mogue predati ime datoteke kao argument dok se
pokree aplikacija. Ime datoteke koje se prosleuje treba da se koristi za otvaranje i
prikazivanje iste u okviru za tekst.
1. Promenite implementaciju metode Main() tako da joj se moe proslediti argument:

2. Sada moramo da promenimo implementaciju konstruktora frmMain da koristi string:

3. Moramo i da implementiramo metodu OpenFile() koja otvara datoteku i ispunjava TextBox


podacima iz nje:

10

Ovde koristimo klase StreamReader i File za itanje datoteke. Da bismo koristili ove klase bez
dodavanja imenovanog prostora svaki put, moramo dodati iskaz using System. 10 na poetku
naeg programa.
4. Sada moemo da pokrenemo aplikaciju iz komandne linije gde predajemo naziv datoteke.
Datoteka e biti trenutno otvorena i prikazana u okviru za tekst, kao to moe da se vidi na slici
ispod:

Kako to radi
Dodavanjem string [ ] u parametre metode Main() moemo koristiti bilo koje argumente
komandne linije koje je korisnik naveo pri pokretanju aplikacije:

U metodi Main() proveravamo da li su argumenti predati, koristei svojstvo Length. Ako se


argument predaje, prvi argument se upisuje u promenljivu fileName koja se koristi za
prosleivanje konstruktoru frmMain:

Unutar Visual Studio .NET-a mogue je deformisati parametre komandne linije za otklanjanje
greaka. U Solution Exploreru morate samo izabrati projekat i izabrati Project\Properties. Ako
izaberete Configuration Properties \ Debugging u levom stablu, pojavljuje se dijalog koji je
pokazan ispod i moete uneti argumente komandne linije.

11

U konstruktoru frmMain proveravamo da li je vrednost promenljive fileName ve postavljena.


Ako jeste, postavljamo promenljivu lanicu fileName i pozivamo metodu OpenFile() da otvori
datoteku. Koristimo razliit metod OpenFile() i ne stavljamo pozive za otvaranje datoteke i
popunjavanje kontrole TextBox direktno u konstruktoru klase jer OpenFile()
moe da se
koristi ponovo u drugim delovima programa.

U metodi OpenFile() koristimo statiki metod OpenText() klase File da bismo otvorili datoteku i
dobili vraen objekat StreamReader. Klasa StreamReader se onda koristi da se proita
datoteka pomou metode ReadToEnd() koja uitava tekst kao string koji je prosleen objektu
TextBox. Objekat StreamReader bi trebalo da se zatvori posle upotrebe da bi se oslobodili
upravljani i neupravljani resursi. Ovo emo uiniti iskazom using. Tako using poziva Dispose()
na kraju bloka, a Dispose() implementacija klase StreamReader na kraju poziva Close() da
zatvori datoteku:

Poto operacije sa datotekama mogu lako da generiu izuzetke, na primer kada korisnik nema
odgovarajua prava pristupa datoteci, ili kad sama datoteka ne postoji, kod je stavljen unutar
bloka try. U sluaju IO izuzetka, pokazuje se okvir sa porukom korisniku da ga informie o
problemu, ali aplikacija i dalje radi:
Ako upiemo nepostojee ime datoteke kada pokrenemo aplikaciju, pojavljuje se ovaj okvir sa
porukom:

12

Dodavanje dijaloga za otvaranje datoteke


Sad moemo da itamo datoteke sa ovim jednostavnim programom za ureivanje, predajui
ime datoteke pri pokretanju aplikacije. Ali naravno, koristimo opte dijalog klase koje emo
dodati odmah aplikaciji.
1. U kategoriji Windows Forms okvira sa alatima moemo da naemo komponentu
OpenFileDialog. Dodajte ovu komponentu u dizajner Windows formulara. Menjamo samo tri
svojstva: ime instance u dlgOpen, svojstvo Filter e biti postavljeno na sledei string, a
svojstvo FilterIndex je postavljeno na 2 da bi Pupin dokumenti bili podrazumevani izbor:
Text Documents (*.txt)|*.txt|All Files (*.*)|*.*|Pupin Documents (*.puptext)|*.puptext

Kako to radi
Dodavanjem komponente OpenFileDialog u dizajner Windows formulara, novi privatni lan je
dodat klasi frmMain:

U dizajneru koda Windows formulara, initializeComponent(), nova instanca klase


OpenFileDialog se kreira i odgovarajua svojstva se postavljaju. Da bi se video sledei kod u
programu za ureivanje koda, morate da pritisnete + znak linije Windows Forms Designer
generated code i onda + znak linije private void InitializeComponent() :

13

....
....

Sa podrkom dizajnera Windows formulara, pravimo novu instancu klase OpenFileDialog i


postavljamo njena svojstva. Sada smo spremni da prikaemo dijalog.
Prikazivanje dijaloga OpenFileDialog
Dodajte rutinu za obradu dogaaja Click ulaza u meni Open, u kojoj prikazujemo dijalog i
itamo izabranu datoteku sa sledeim kodom:

Kako to radi
Metoda ShowDialog() prikazuje dijalog za otvaranje datoteka i vraa dugme koje je korisnik
pritisnuo. Nita neemo uraditi sve dok korisnik ne pritisne dugme OK. To je razlog zato
proveravamo DialogResult .OK u iskazu if. Ako korisnik poniti dijalog, nita neemo uraditi:

14

Zatim emo uzeti ime izabrane datoteke pristupajui svojstvu FileName klase OpenFileDialog i
postavljajui promenljivu lanicu fileName na ovu vrednost. Ovo je vrednost koja se koristi u
metodi OpenFile. Takoe bi bilo mogue direktno otvoriti datoteku sa klasom OpenFileDialog
pozivajui metod dlgOpenFile.OpenFile() koji nam ve vraa objekat Stream, ali poto ve
imamo metod OpenFile koji otvara i ita datoteku, koristiemo njega:

Pokretanje Prostog Editora


1. Sada moemo da pokrenemo na jednostavni program za
ureivanje teksta. Samo ulazi menija New i Open trenutno rade.
Save i Save As... e biti implementirani u sledeoj sekciji.
Izborom ulaza u meni File | Open... pojavljuje se OpenFileDialog i
moemo izabrati datoteku. Pretpostavlja se da trenutno nemate
datoteke sa oznakom za tip .puptext. U ovom trenutku ne moemo
da snimamo datoteke, pa zato izaberite drugaiji tip datoteke u
dijalogu za otvaranje datoteke, ili moete iskopirati tekst datoteku
tako da ima oznaku za tip .puptext:

Izaberite tekst datoteku - pritiskanjem dugmeta Open tekst se pojavljuje u okviru za tekst
dijaloga.

15

U ovom momentu ve moemo itati postojee datoteke. Sada bi bilo odlino ako bismo preli
na stvaranje novih i menjanje starih. Koristiemo SaveFileDialog da bismo ovo uinili.

Klasa SaveFileDialog
Klasa SaveFileDialog je vrlo slina klasi OpenFileDialog i one imaju skup zajednikih svojstava.
Ovde neemo priati o onim svojstvima koja operiu na isti nain kao kod dijaloga za otvaranje
datoteka. Umesto toga, usmeriemo panju na svojstva specifina za dijalog za snimanje
datoteka, kao i na mesta gde se primena optih svojstava razlikuje.

Naslov
Pomou svojstva Title moete postaviti naslov dijaloga slino kao u klasi OpenFileDialog. Ako
nita nije postavljeno, podrazumevani naslov je Save As.

Oznake za tip datoteke


Oznake za tip datoteka se koriste da poveu datoteke sa aplikacijama. Najbolje je dodati
oznaku za tip datoteci; u suprotnom, Windows nee biti u mogunosti da zna koja aplikacija bi
trebalo da se iskoristi za otvaranje datoteke, i verovatno je da ete i vi to zaboraviti.
AddExtension je svojstvo tipa Boolean koje definie da li e oznaka za tip datoteke biti
automatski dodata imenu koje korisnik unese. Ako korisnik sam unese oznaku, dodatna oznaka
nee biti dodavana. Tako da ako korisnik unese za ime datoteke test, datoteka test. txt e biti
upisana na disk. Ako se upie naziv test.txt, datoteka koja e biti snimljena e i dalje biti
test.txt, a ne test.txt.txt.
Svojstvo DefaultExt postavlja nastavak za tip datoteke koji e se koristiti ako korisnik ne upie
istu. Ako ostavite svojstvo praznim, oznaka tipa datoteke koja je definisana sa trenutno
izabranim svojstvom Filter e biti koriena umesto njega. Ako postavite i svojstvo Filter i
svojstvo DefaultExt, DefaultExt e biti korien bez obzira na Filter.

Validacija
Za automatsku validaciju imena datoteke, imamo svojstva ValidateNames, CheckFileExists i
CheckPathExists, kao i kod klase OpenFileDialog. Razlika izmeu klasa OpenFileDialog i
SaveFileDialog jeste u tome to je za klasu SaveFileDialog; podrazumevana vrednost za
svojstvo CheckFIleExists - false, to znai da moete dostavite ime novoj datoteci za snimanje.

Snimanje preko postojeih datoteka


Kao to smo videli, validacija imena datoteka je slina kao kod klase OpenFileDialog. Ali ipak
za klasu SaveFileDialog postoji jo provera koje treba sprovesti i jo svojstava za podeavanje.
Na prvom mestu, ako postavite svojstvo CreatePrompt na true, korisnik e biti upitan da li eli
da se napravi nova datoteka. Ako se svojstvo OverwritePrompt postavi na true, to znai da je
korisnik upitan da li zaista eli da presnimi preko postojee datoteke. Predefinisana vrednost za

16

svojstvo OverwritePrompt je true, a za CreatePrompt je false. Sa ovim podeavanjem sledei


dijalog se prikazuje ako korisnik eli da snimi preko postojee datoteke:

Svojstva klase FileSaveDialog


Kao i u prethodnom dijalogu, ovde ponovo imamo sliku koja sumira sva svojstva klase
FileSaveDialog:

Dodavanje dijaloga SaveFileDialog


1. Moemo da dodamo dijalog SaveFileDialog slian dijalogu OpenFileDialog u dizajneru
Windows formulara: izaberite komponentu SaveFileDialog iz okvira sa alatima i spustite je na
formular. Promenite svojstvo Name u dlgSaveFile, FileName u Untitled, FilterIndex u 2, i
Filter u sledei string kao to smo radili ranije sa OpenFileDialog. Poto samo elimo da
dopustimo oznake tipova datoteka .txt i .puptext da budu snimljene sa ovim programom za
ureivanje, *.* e biti izostavljeno:
Text Document (*.txt)|*.txt|Pupin Documents (*.puptext)|*.puptext

2. Dodajte rutinu za obradu dogaaja Click za ulaz menija Save As i dodajte sledei kod. U
ovom kodu prikazaemo dijalog SaveFileDialog pomou metode ShowDialog(). Kao i sa
dijalogom OpenFileDialog, samo nas interesuje rezultat ako je korisnik pritisnuo dugme OK.
Pozvaemo metod SaveFile() koji snima datoteku na disk. Ova metoda mora da bude
implementirana u sledeem koraku:

17

3. Dodajte metod SaveFile(), kao to se moe videti ovde, u vau datoteku:

Slino metodi OpenFile, koristiemo klasu File da otvorimo datoteku, ali sada je otvaramo za
upis sa OpenWrite(). Metod OpenWrite() vraa objekat Stream koji je prosleen konstruktoru
klase StreamWriter. Metoda Write() klase StreamWriter upisuje sve podatke iz kontrole
TextBox u datoteku. Na kraju bloka using, objekat StreamWriter se zatvara. Stream objekat je
povezan sa objektom writer; stream se takoe zatvara, i nema potrebe za pozivom dodatnog
metoda Close() objekta stream.
4. Posle izgradnje projekta, moemo
pokrenuti aplikaciju koristei meni
Debug | Start Visual Studio .NET-a.
Napiite neto teksta u TextBox i
izaberite meni File | Save As... kao
to je pokazano na slici pored:

Dijalog SaveFileDialog e se pojaviti, kao to je pokazano ispod. Sada moete snimiti datoteku i
ponovo je otvoriti da napravite jo izmena:

18

Implementiranje rutine za snimanje datoteke


Moemo da izvedemo opciju Save As, ali jednostavni Save nije dostupan u ovom trenutku.
Dodajte rutinu za obradu dogaaja Click stavke menija Save i dodajte sledei kod:

Kako to radi
Sa menijem Save, datoteka bi trebalo da bude snimljena bez otvaranja dijaloga. Postoji jedan
izuzetak ovom pravilu, a to je da ako se kreira novi dokument, a korisnik nije naveo ime
datoteke, tada rutina za snimanje treba da radi kao to to ini Save As i prikae dijalog za
snimanje datoteke.
Sa promenljivom lanicom fileName lako moemo da proverimo da li je datoteka otvorena ili je
ime jo postavljeno na inicijalnu vrednost Untitled posle kreiranja novog dokumenta. Ako iskaz
if vraa true, pozivamo rutinu miFileSaveAs_Click() koju smo prethodno implementirali za
meni Save As.
U drugom sluaju, kada je datoteka otvorena i korisnik sad bira meni Save, izvravanje prolazi
u blok else. Moemo koristiti isti metod SaveFile()koji smo prethodno implementirali.
Postavljanje naslova formulara
1. Sa Notepadom, Wordom i drugim Windows aplikacijama ime dokumenta koji se trenutno
ureuje prikazano je u naslovu aplikacije. Trebalo bi i ovu mogunost da dodamo.
Napravite novu funkciju lanicu SetFormTitle() i dodajte ovu implementaciju:

Klasa Fileinfo se koristi da se dobije ime datoteke bez putanje koja prethodi, a nalazi se u
promenljivoj filename. Klase Fileinfo i StreamWriter su pokrivene u nekom drugom
predavanju. Dodajte poziv ovog metoda u rutine miFileNew_Click(), miFileOpen_Click(), i
miFileSaveAs_Click() posle postavljanja promenljive lanice fileName, kao to se moe videti
u sledeim segmentima koda:

19

Kako to radi
Svaki put kada se ime datoteke promeni, svojstvo Text aktuelnog formulara e biti promenjeno
na ime datoteke na koje je nadovezano ime aplikacije.
Pokrenuvi aplikaciju sada vidite sledei ekran. Ovde, poto uredujemo datoteku uzorak.txt,
ova informacija je prikazana u naslovu formulara:

Sada je na jednostavni program za ureivanje kompletan: moemo otvarati, praviti i snimati


datoteke. Da li smo zavrili? Ne ba - trebalo bi da dodamo i mogunost tampanja.

tampanje
Sa tampanjem, moramo da brinemo o izboru tampaa, podeavanjima za stranu, i o tome
kako da tampamo viestruke stranice. Sa .NET klasama u imenovanom prostoru
System.Drawing.Printing zadatak nam je znatno olakan.
Pre nego to pogledamo klasu PrintDialog koja omoguava izbor tampaa, pogledaemo kako
.NET rukuje tampanjem. Osnova za tampanje je klasa PrintDocument iji metod Print()
zapoinje lanac poziva koji se zavrava pozivom OnPrintPage(), koji je odgovoran za

20

predavanje izlaza na tampa. U svakom sluaju, pre nego to uemo dublje u implementaciju
koda za tampu, pogledajmo neto detaljnije .NET klase za tampanje.

Arhitektura tampanja
Sledei dijagram pokazuje glavne delove arhitekture tampanja u formularu dijagrama koji
razjanjava odnose izmeu klasa i nekih svojstava i metoda:

Pogledajmo na funkcionalnost ovih klasa:


Ponimo sa najvanijom klasom, PrintDocument. U dijagramu vidite da skoro sve druge
klase imaju komunikaciju sa ovom klasom. Da bi se odtampao dokument, instanca klase
PrintDocument je neophodna. U drugom dijagramu, pogledaemo sekvencu tampanja
koju inicira ova klasa. Ali pre toga, pogledajmo takoe i druge klase.
Klasa PrintController kontrolie tok zadatka za tampu. Poevi zadatak tampe,
kontroler tampe ima dogaaje za poetak tampe, za svaku stranicu i za kraj tampe.
Klasa je apstraktna jer se implementacija razlikuje od normalne tampe i pregleda
tampanja.
Moemo dobiti i podesiti konfiguraciju tampaa kao to je dvostrana tampa,
orijentacija papira (vertikalna ili horizontalna), kao i broj kopija, sa klasom
PrinterSettings.
Na kojem tampau emo tampati i kako e PrinterSettings biti konfigurisan, posao je
klase PrintDialog. Ova klasa je izvedena iz klase CommonDialog kao i ostale klase za
dijalog sa kojima smo se sretali, i moda ve imate ideju kako e biti upotrebljena.
Klasa PageSettings postavlja veliinu i granice strane, i da li je strana u koloru ili crnobela. Konfiguracija ove klase moe da bude izvedena sa klasom PageSetupDialog koja je,
takoe, izvedena iz klase CommonDialog.

Redosled tampanja
Sad kada znamo uloge klasa u arhitekturi tampanja, pogledajmo glavni redosled tampe.
Dijagram ispod pokazuje glavne uesnike, aplikaciju koju elimo da napiemo, instancu klase
PrintDocument i PrintController u vremenskoj sekvenci:

21

Aplikacija mora da pozove metod Print() klase PrintDocument. Ovo poinje sekvencu
tampanja. Kako objekat PrintDocument sam nije odgovoran za tok tampe, zadatak je dat
objektu PrintController pozivanjem metoda Print() ove klase.
Kontroler tampe sad preuzima akciju i obavetava PrintDocument da je tampanje poelo
pozivajui metod OnBeginPrint(). Ako naa aplikacija treba neto da uradi na poetku zadatka
za tampu, moramo da registrujemo rutinu za obradu dogaaja u klasi PrintDocument tako da
budemo obaveteni u naoj klasi aplikacije. Na pokazanom dijagramu pretpostavlja se da smo
registrovali rutinu OnBeginPrint(), tako da se ona poziva iz klase PrintDocument.
Kada je poetna faza zavrena, PrintControler ulazi u metod PrintLoop() da bi pozvao metod
OnPrintPage() u klasi PrintDocument za svaku stranu koja treba da se odtampa. Metod
OnprintPage() poziva sve ratine za obradu dogaaja PrintPage. Moramo da implementiramo
takvu ratinu u svakom sluaju; u suprotnom, nita ne bi bilo odtampano. U dijagramu iznad
moete da vidite da se rutina naziva OnPrintPage().
Posle zadnje odtampane stranice, PrintController poziva metod OnEndPrint() u klasi
PrintDocument. Takoe, opciono, moemo da implementiramo rutinu koja treba da bude
pozvana na ovom mestu.
Najvanija stvar koju treba da znamo jeste:
Moemo da implementiramo kod za tampu u rutini za obradu dogaaja PrintDocument.
PrintPage. Ona e biti pozivana za svaku stranicu koja je e biti odtampana. Ako postoji kod
za tampu koji bi trebalo da se poziva samo jednom po zadatku tampe, moramo da
implementiramo rutine za obradu dogaaja BeginPrint i EndPrint.

22

Dogaaj PrintPage
Sada moramo da implementiramo rutinu za obradu
PrintPageEventHandler definie argumente ove rutine:

dogaaja

PrintPage.

Delegat

Public delegate void PrintPageEventHandler(object sender, PrintPageEventArgs e);

Kao to moete videti, dobijamo objekat tipa PrintPageEventArgs. Moete da pogledate nazad
u dijagramu klasa da proverite glavna svojstva ove klase. Ova klasa ima veze sa klasama
PageSettings i Graphics; prva nam omoguava da postavimo veliinu papira, margine, i da
dobijemo informacije o samom tampau. Klasa Graphics, sa druge strane, omoguava nam
pristup kontekstu tampaa i slanje stringova, linija i krivih.
GDI oznaava Graphics Device Interface i omoguava nam odreeni grafiki izlaz na ureaj kao
to je ekran i tampa. GDI+je sledea generacija GDI-ja koja dodaje karakteristike kao to su
etke sa vie nivoa i alfa pretapanje.
Kroz sledei primer videete da je dodavanje mogunosti tampe aplikacijama prilino lak
zadatak.
Dodavanje stavke Print u meni
Pre nego to moemo da dodamo dijalog PrintDialog, moramo da dodamo par ulaza u meni za
tampu. Dodajte dva graninika i stavke menija Print, PrintPreview, PageSetup i Exit.
Ovde su navedena svojstva Name i Text novih stavki menija:
Ime stavke menija
miFilePrint
miFilePrintPreview
miFilePageSetup
miFileExit

Text
&Print
Print Pre&view...
Page Set&up...
E&xit

Meni bi trebalo da izgleda kao na sledeoj slici:

Dodavanje komponente PrintDocument i rutine za obradu dogaaja


1. Prevucite komponentu PrintDocument iz okvira sa alatima i spustite je na formular.
Promenite ime u PrintDocument, i dodajte rutinu OnPrintPage() za obradu dogaaja Printpage
izborom dugmeta Events u prozoru Properties. Tada dodajte ovaj kod implementaciji rutine za
obradu dogaaja:

23

2. Zatim dodajte rutinu za obradu dogaaja Click menija Print da biste pozvali metod Print()
klase PrintDocument:

3. Sada moete da izgradite i pokrenete aplikaciju i odtampate dokument. Naravno, morate da


imate tampa instaliran da bi primer radio.
Kako to radi
Metod Print() objekta printDocument poziva dogaaj PrintPage objekta printDocument uz
pomo klase PrintController klase:

U rutini OnPrintPage(), podelimo tekst unutar okvira za tekst red po red, koristei metod
String.Split() i znak za novu liniju \n. Rezultujui stringovi su upisani u promenljivu lines:

Zavisno od toga kako je tekst kreiran, redovi nisu samo razdvojeni znakom \n , ve i znakom \r.
Sa metodom TrimEnd() string klase, znak \r je otklonjen iz svakog stringa:

U drugom iskazu foreach u kodu ispod, moete videti da prolazimo kroz sve linije i aljemo
svaku liniju na tampa pozivom metoda e.Graphics.Drawstring(). e je promenljiva tipa
PrintPageEventArgs gde je svojstvo Graphics povezano sa kontekstom tampaa. Kontekst
tampaa omoguuje crtanje na ureaju za tampanje; klasa Graphics ima svoje metode za
iscrtavanje u ovom kontekstu.

24

Poto jo ne moemo da izaberemo tampa, koristimo podrazumevani tampa, iji detalji se


uvaju u Windows registracionoj bazi.
Sa metodom Drawstring() koristimo font Arial sa veliinom od 10 taaka i crnom linijom na
izlazu tampaa. Pozicija za izlaz je definisana promenljivama x i y. Horizontalna pozicija je
fiksirana na 20 piksela; vertikalna pozicija se poveava za svaki red:

tampa koju smo dosad uradili nije bez greke:


Izlaz tampe je poslat na podrazumevani tampa kao to je postavio korisnik u Control
Panelu. Bilo bi bolje za nau aplikaciju da korisnik moe da bira tampa. Koristiemo
klasu PrintDialog za ovo.
Font je fiksiran. Da bi se omoguilo korisniku da izabere font, moemo koristiti klasu
FontDialog koju emo posle pogledati detaljnije.
Okviri strane su fiksirani na unete vrednosti u naem programu. Da bi korisnik postavio
vrednosti za razliite okvire strane, koristiemo klasu PageSetupDialog.
tampanje vise strana ne radi. Ako se dokument za tampu prostire na vise strana, samo
prva strana se tampa. Takoe bi bilo lepo da se i zaglavlje (na primer, ime datoteke) i
fusnota (na primer, broj strane) tampaju.
Prema tome, nastavimo sa procesom tampe da bismo sredili ove stavke.

tampanje vie strana


Dogaaj Printpage biva pozivan za svaku stranu tampe. Moramo samo da obavestimo objekat
PrintController da trenutna strana u tampi nije zadnja strana, podeavajui svojstvo
HasMorePages klase PrintPageEventArgs na vrednost true.
Izmena metoda OnPrintPage za tampanje vise strana
1. Morate takoe deklarisati promenljivu lanicu lines tipa string[ ] i promenljivu linesPrinted
tipa int u klasi frmMain:

25

2. Promenite rutinu OnPrintPage(). U prethodnoj implementaciji OnPrintPage() podelili smo


tekst u linije. Poto se metod OnPrintPage() poziva za svaku stranicu, deljenje teksta u redove
je potrebno samo jednom, na poetku nae operacije tampe. Uklonite sav kod iz ratine
OnPrintPage() i zamenite ga novom implementacijom:

3. Dodajte rutinu za obradu dogaaja Beginprint objekta printDocument. Rutina


OnBeginPrint() se poziva jednom za svaki zadatak tampe, i ovde pravimo na niz lines:

26

4. Posle izgradnje projekta moete pokrenuti zadatak za tampu dokumenta sa vise strana.
Kako to radi
Poinjanje zadatka tampe metodom Print() objekta PrintDocument za uzvrat poziva rutinu
BeginPrint() jednom i OnPrintPage() za svaku stranu.
U rutini BeginPrint(), podelimo tekst iz okvira za tekst u niz stringova. Svaki string u nizu
predstavlja jednu liniju, jer je delimo sa znacima nove linije (\n) i sklanjamo znak povratka na
poetak reda (\r), kao to smo radili i ranije:

Rutina OnPrintPage() se poziva posle BeginPrint(). elimo da nastavimo tampanje dokle god je
broj odtampanih linija manji od broja linija koliko treba da odtampamo. Svojstvo
lines.Length vraa broj stringova u nizu lines. Promenljiva linesPrinted se poveava sa svakom
linijom koju poaljemo tampau:

Posle tampanja linije, proveravamo da li je novo izraunata vertikalna pozicija van okvira
strane. Dodatno smanjujemo okvire za 80 piksela, jer zapravo ne elimo da tampamo do
samog kraja papira; mnogi tampai ovo ionako ne mogu da urade. Ako je ova pozicija
dostignuta, svojstvo HasMorePages klase PrintPageEventArgs je podeeno na true, da bi
kontroler znao da se metod OnPrintPage() mora pozvati jo jednom. Zapamtite da objekat
PrintController ima metod PrintLoop(), koji ima sekvencu za svaku stranu koju tampa.
PrintLoop() e se zaustaviti ako svojstvo HasMorePages ima vrednost false. Predefinisana
vrednost svojstva HasMorePages je false, tako da se tampanje zaustavlja:

Podeavanje strane
Margine strane do sada su fiksirane u programu. Promenimo aplikaciju da dozvoli korisniku da
postavi margine na strani. Da bi ovo bilo mogue, dostupna je jo jedna klasa dijaloga:
pageSetupDialog.

27

Ova klasa nam omoguuje da konfiguriemo veliinu i izvor papira, orijentaciju i margine
papira, a poto te opcije zavise od tampaa, izbor tampaa moe da se izvri i iz ovog
dijaloga.

Papir
Vrednost true za svojstvo AllowPaper znai da korisnik moe da bira veliinu i izvor papira.
Svojstvo PageSetupDialog.PageSettings.PaperSize vraa instancu klase PaperSize gde moemo
da itamo visinu, irinu i ime papira, sa svojstvima Height, Width i PaperName. PaperName
navodi imena kao Letter i A4. Svojstvo Kind vraa enumeraciju gde moemo da dobijemo
vrednost iz enumeracije PaperKind. Ovo moe da bude jedna od tri vrednosti: European,
American ili Japanese.
Svojstvo PageSetupDialog.PageSettings.Papersource vraa instancu klase PaperSource gde
moemo da proitamo ime izvora i tipa papira (kao i to da li je tampa ispravno konfigurisan
sa podeavanjima za tampa).

Margine
Postavljanje svojstva AllowMargins na true dozvoljava korisniku da postavi vrednost margine za
tampu. Moemo definisati minimalne vrednosti za korisnikov unos, podeavajui svojstvo
koristimo
svojstvo
MinMargins.Da
bismo
proitali
margine,
PageSetupDialog.PageSettings.Margins. Vraeni objekat Margins ima svojstva Bottom, Left,
Right i Top.

Orijentacija papira
Svojstvo AllowOrientation definie da li korisnik moe da bira orijentaciju papira (portrait ili
landscape).
Izabrana
vrednost
se
moe
proitati
iz
svojstva
PageSetupDialog.PageSettings.Landscape, to daje vrednost tipa Boolean za naglaavanje
landscape reima sa true i portrait reima sa false.

tampa
Svojstvo AllowPrinter definie da li korisnik moe da bira tampa. Zavisno od vrednosti ovoga
svojstva, dugme Printer je vidljivo ili ne. Rutina za obradu pritiska ovog dugmeta otvara dijalog
PrintDialog koji emo koristiti dalje.

Svojstva dijaloga PageSetupDialog


Slika ispod nam daje pregled svojstava koja ukljuuju ili iskljuuju posebne opcije ovog
dijaloga, kao i koja svojstva mogu da se koriste za pristup ovim vrednostima:

28

Dodavanje dijaloga PageSetupDialog


1. Dodajte komponentu PageSetupDialog iz okvira sa alatima u dizajneru Windows formulara.
Postavite svojstvo Name na dlgPageSetup i Document na PrintDocument, kako biste povezali
dijalog sa dokumentom za tampu.
Tada dodajte rutinu za obradu dogaaja Click stavke u meniju Page Setup, i dodajte kod za
prikaz dijaloga koristei metod ShowDialog(). Nije neophodno proveravati povratnu vrednost
metoda ShowDialog() ovde, jer implementacija rutine za obradu dogaaja Click dugmeta OK
ve postavlja nove vrednosti u povezanom objektu PrintDocument:

2. Sada promenite implementaciju metoda OnPrintPage() da koristi margine koje su


postavljene u dijalogu PageSetupDialog. U naem kodu, promenljive x i y su postavljene na
svojstva MarginBounds.Left i MarginBounds.Bottom klase PrintPageEventArgs. Proveravamo
margine pomou svojstva MarginBounds.Bottom:

29

3. Sada moete izgraditi projekt i pokrenuti aplikaciju. Izborom File | Page Setup pokazuje se
sledei dijalog. Moete promeniti margine i tampati sa podeenim okvirima strane:

Ako
prikazivanje
dijaloga
PageSetupDialog
ne
prode,
izuzetak
tipa
System.ArgumentException se generie; to je verovatno zato to ste zaboravili da poveete
objekat PrintDocument sa kontrolom PageSetupDialog. Dijalogu PageSetupDialog treba
povezani objekat PrintDocument da upita i podesi vrednosti koje su prikazane u dijalogu.

Klasa PrintDialog
Klasa PrintDialog dozvoljava korisniku da izabere eljeni tampa od instaliranih tampaa, da
izabere broj kopija, i neka podeavanja tampaa kao to su izgled i izvor papira. Poto je klasa
PrintDialog veoma jednostavna za korienje, poeemo odmah sa dodavanjem dijaloga
PrintDialog naoj aplikaciji.
Dodavanje dijaloga PrintDialog
1. Dodajte komponentu PrintDialog iz okvira sa alatima na formular. Postavite svojstvo Name
na dlgPrint i Document na PrintDocument.
Promenite implementaciju rutine za obradu dogaaja Click stavke menija Print, na sledei
nain:

2. Izgradite i pokrenite aplikaciju. Izborom File | Print otvara se PrintDialog. Sada moete
izabrati tampa za tampu dokumenta:

30

Opcije za PrintDialog
U naem programu Prosti Editor, nismo menjali nijedno svojstvo dijaloga PrintDialog. Ovaj
dijalog ima takoe neke opcije. U gornjem dijalogu, moete videti tri grupe: Printer, Print
range i Copies:
U grupi Printer ne morate izabrati samo tampa; postoji i opcija Print to File. Ova
opcija je podrazumevano omoguena, ali ne i potvrena. Izborom ovog polja za potvrdu
omoguuje se tampa u datoteku, umesto na tampa. Moete onemoguiti ovu opciju
postavljanjem svojstva AllowPrintToFile na false . Ako korisnik izabere ovu opciju,
sledei dijalog se otvara pozivom printDocument.Print() traei ime datoteke u
koju e se tampati.

U sekciji dijaloga Print Range samo All moe da bude izabran - opcije Pages i Selection
su podrazumevano neaktivne. Pogledaemo kako ove opcije mogu da budu
implementirane u sledeoj sekciji.
Grupa Copies dozvoljava korisniku da izabere broj kopija za tampu.

tampanje izabranog teksta


Ako elite da omoguite da se tampa samo izabrani tekst, moete da aktivirate ovo radio
dugme postavljanjem svojstva AllowSelection na vrednost true . Takoe morate da promenite
kod za tampu tako da samo izabrani tekst biva odtampan.
Dodavanje tampanja izabranog teksta
1. Dodajte naglaeni kod u rutinu za obradu dogaaja Click dugmeta Print:

31

U naem programu, sve linije koje e biti odtampane postavljene su u rutini OnBeginPrint().
Promenite implementaciju ove metode:

Sada moete izgraditi i pokrenuti program. Otvorite datoteku, izaberite neki tekst, pokrenite
dijalog za tampanjem iz menija File |Print, i izaberite opciono dugme Selection iz grupe Print
Range. Poto je ovo izabrano, pritiskanje dugmeta Print e da odtampa samo izabrani tekst.
Kako to radi
Postavili smo svojstvo AllowSection na true samo ako je neki tekst izabran. Pre nego to smo
prikazali PrintDialog, moramo da proverimo da li je tekst izabran. To se ini proverom da li je
vrednost svojstva SelectedText okvira za ureivanje razliita od null. Ako je neto teksta
izabrano, svojstvo AllowSelection je postavljeno na true:

OnBeginPrint() se poziva na poetku svakog zadatka za tampu. Pristupom svojstvu


printDialog.PrinterSettings.PrintRange, dobijamo informaciju da li je korisnik izabrao opciju
Selection. Svojstvo PrintRange vraa enumeraciju PrintRange koja moe da ima vrednosti
AllPages, Selection, ili SomePages:

32

Ako je opcija Selection, dobijamo izabrani tekst string u svojstvu SelectedText kontrole
TextBox. Ovaj string je podeljen na isti nain kao i kompletan tekst:

Za korienje enumeracije PrintRange moramo


System.Drawing.Printing na poetku programa:

da

uvrstimo

imenovani

prostor

using System.Drawing.Printing;

tampanje opsega strana


tampanje opsega strana moe biti implementirano na slian nain kao i tampanje izbora.
Opciono dugme moe biti aktivirano podeavanjem svojstva AllowSomePages na true. Korisnik
sada moe da bira od koje do koje stranice eli da tampa. Ipak, gde su granice stranica u
naem jednostavnom programu za ureivanje? Koja je zadnja stranica? Trebalo bi da podesimo
zadnju stranicu izmenama u svojstvu PrintDialog.PrinterSettings.ToPage.
Kako korisnik zna brojeve stranica koje eli da odtampa? To nije problem u aplikacijama kao
to je Microsoft Word, gde Print Layout moe da bude izabran kao pogled ekrana. Ovo nije
mogue sa jednostavnom kontrolom TextBox koju koristimo u naem Prostom Editoru. To je
razlog zato neemo implementirati ovu mogunost u nau aplikaciju.
Naravno, ovo moete uraditi kao vebu. Svojstvo AllowSomePages mora biti postavljeno na
true. Pre prikazivanja dijaloga PrintDialog, moete takoe da postavite svojstvo
PrinterSettings.ToPage na maksimalan broj strana.

Svojstva dijaloga PrintDialog


Da sumiramo svojstva koja utiu na izgled dijaloga PrintDialog ponovo sa slikom:

Pregled pre tampanja


Moda korisnik eli da vidi kako e izgledati tampana strana. To je razlog zato emo iskoristiti
pregled pre tampanja. Implementiranje pregleda pre tampanja u .NET okruenju je lako.
Moemo upotrebiti klasu PrintPreviewControl koja se koristi da uradi pregled dokumenta u
formularu, da pokae kako e biti odtampana. PrintPreviewDialog je dijalog koji obmotava
kontrolu.

33

Dijalog PrintPreviewDialog
Posmatrajui svojstva i listu naslea iz MSDN dokumentacije za klasu PrintPreviewDialog,
moete lako videti da je ovo formular, a ne obmotani opti dijalog - klasa se razlikuje od
System.WindowsForms.Form, i moete da radite sa njom sa formularima - klasa je izvedena iz
System.Windows.Forms.Form, i moete da radite sa njom kao sa formularima. Dodaemo
klasu PrintPreviewDialog u nau aplikaciju Prosti Editor.
Dodavanje dijaloga Print Preview
1. Dodajte komponentu PrintPreviewDialog u dizajneru Windows formulara. Postavite
svojstvo Name na dlgPrintPreview, i Document na PrintDocument.
Dodajte i implementirajte rutinu za obradu dogaaja Click stavke menija Print Preview:

Klasa PrintPreviewControl
Pregled pre tampanja u Microsoft Wordu i WordPadu je drugaiji od dijaloga
PrintPreviewDialog u tome to se u ovim aplikacijama pregled ne pojavljuje u sopstvenom
dijalogu, nego u glavnom prozoru aplikacije.
Da bi se izvelo isto, moete da postavite klasu PrintPreviewControl u va formular. Svojstvo
Document mora da bude postavljeno na objekat PrintDocument, a Visible na false. U rutini
moete postaviti svojstvo Visible na true kako biste videli pregled pre tampanja. Tada je
PrintPreviewControl ispred drugih kontrola, kao to je pokazano na sledeoj slici:

34

Iz naslova i jedne jedine stavke u meniju File moete da vidite da je prikazan glavni prozor
aplikacije Prosti Editor. Treba jo da dodamo neke elemente koji kontroliu klasu
PrintPreviewControl da vri zumiranje, tampu, i prikazivanje teksta u 2, 3, 4 ili 6 strana, itd.
Posebna paleta sa alatkama moe da se koristi da uini ove mogunosti dostupnim. Klasa
PrintPreviewDialog ve ovo ima implementirano, kao to moete da vidite u sledeoj slici.

Klase FontDialog i ColorDialog


Poslednji dijalozi o kojima emo govoriti u ovom predavanju su FontDialog i ColorDialog.
Ovde emo se zadrati na diskusiji dijaloga zapostavljanje fonta i boje, a ne i na klasama Font i
Color.

Klasa FontDialog
Klasa FontDialog omoguuje korisniku aplikacije izbor fonta. Korisnik moe da menja font,
stil,veliinu i boju.
Sledea slika bi trebalo da vam omogui pregled svojstava koji menjaju elemente u dijalogu:

35

Klasa FontDialog omoguuje korisniku aplikacije izbor fonta. Korisnik moe da menja font,
stil, veliinu i boju.

Kako se koristi klasa FontDialog


Dijalog moe da se koristi na isti nain kao i u prethodnim dijalozima. U dizajneru Windows
formulara, dijalog moe biti prevuen iz okvira sa alatima i sputen na formular tako da se
kreira instanca klase FontDialog.
Kod koji koristi FontDialog izgleda ovako:

Dijalog FontDialog je prikazan pozivanjem metode ShowDialog(). Ako korisnik pritisne dugme
OK, metod vraa DialogResult.OK. Izabrani font moe da se ita koristei svojstvo Font klase
FontDialog; ovaj font se tada prosleuje svojstvu Font kontrole TextBox.

Svojstva klase FontDialog


Ve smo videli sliku sa svojstvima klase FontDialog, a moemo da vidimo i za ta se ova
svojstva koriste:
Svojstvo

Opis

AllowVectorFonts

Boolean vrednost koja definie da li vektorski fontovi


mogu da budu izabrani u listi fontova.

AllowVerticalFonts

Boolean vrednost koja definie da li se vertikalni


fontovi mogu izabrati u listi fontova. Vertikalni
tekstovi se koriste u zemljama dalekog istoka.
Verovatno nemate vertikalni font instaliran u vaem
sistemu.

FixedPitchOnly
MaxSize
MinSize

Postavljanje svojstva FixedPitchOnly prikazuje samo


fontove fiksirane irine. Sa fontom fiksirane irine
svaki znak ima istu veliinu. Podrazumevano je false .
Definisanje vrednosti za MaxSize svojstvo definie
maksimalnu veliinu fonta koju korisnik moe da
izabere.
Slino kao i MaxSi ze, moete postaviti najmanju
veliinu fonta koju korisnik moe izabrati.

36

ShowApply

Ako dugme Apply treba da bude prikazano, morate da


postavite svojstvo ShowApply na true. Pritiskanjem
dugmeta Apply, korisnik moe da vidi promenu fonta
u aplikaciji bez naputanja tekst dijaloga.

ShowColor

Izbor boje nije podrazumevano prikazan u dijalogu.


Ako elite da korisnik izabere boju fonta u font
dijalogu, morate da postavite svojstvo ShowColor na
true.

ShowEffects

Korisnik moe podrazumevano da izabere polja za


potvrdu Strikeout i Underline da upravlja fontom. Ako
ne elite da ove opcije budu prikazane, morate da
postavite ShowEffects na false.

AllowScriptChange

Postavljanje svojstva AllowScriptChange na false


spreava korisnika da promeni pisma fonta. Dostupna
pisma zavise od izabranog fonta, na primer: font Arial
podrava zapadno, hebrejsko, arapsko, grko, tursko,
baltiko, centalnoevropsko, irilino i vijetnamsko
pismo.

Ukljuivanje dugmeta Apply


Zanimljiva razlika u odnosu na druge prikazane dijaloge jeste to FontDialog podrava dugme
Apply koje podrazumevano nije prikazano. Ako korisnik pritisne dugme Apply, dijalog ostaje
otvoren, ali izbor fonta treba da bude primenjen nad tekstom.
Birajui komponentu FontDialog u dizajneru Windows formulara, moete postaviti svojstvo
ShowApply u prozoru Properties na true. Ali, kako smo obaveteni da li korisnik sad pritiska
dugme Apply? Dijalog je jo otvoren, tako da se metod ShowDialog() jo nee zavriti. Umesto
toga, moemo dodati rutinu za obradu dogaaja Apply klase FontDialog. Ovo moete uiniti
pritiskajui dugme Events u prozoru Properties, i upisivanjem imena rutine za dogaaj Apply.
Kao to moete videti u sledeem kodu, uneto je ime OnApplyFontDialog. U ovoj rutini moete
pristupiti izabranom fontu u dijalogu FontDialog koristei promenljivu lanicu klase FontDialog:

Klasa ColorDialog
Klasa FontDialog nema ni priblino tako mnogo svojstava za podeavanje kao ColorDialog. Sa
klasom ColorDialog korisniku je mogue da podesi posebne boje, ako ne eli ni jednu od
ponuenih osnovnih boja; ovo se radi podeavanjem svojstva AllowFullColor. Deo sa
konfigurisanjem posebnih boja u dijalogu moe biti automatski proiren svojstvom FullColor.
Svojstvo SolidColorOnly definie da se mogu koristiti samo osnovne boje. Svojstvo
CustomColors moe se koristiti za dobijanje i konfigurisanje proizvoljnih boja:

37

Kako se koristi dijalog ColorDialog


Komponenta ColorDialog moe biti prevuena iz okvira sa alatima i sputena na formularu
dizajneru Windows formulara, kao to smo radili ve sa drugim dijalozima. Metod ShowDialog()
prikazuje dijalog dok korisnik ne pritisne dugme OK ili Cancel. Moete proitati izabranu boju
pristupanjem svojstvu Color dijaloga, kao to se vidi u sledeem primeru koda:
if (dlgColor.ShowDialog() == DialogResult.OK
{
txtboxEdit.ForeColor = dlgColor.Color;

Svojstva klase ColorDialog


Svojstva koja utiu na izgled dijaloga su prikazana u ovoj tabeli:

Svojstvo

Opis

AllowFullOpen

Podeavanje ovog svojstva na false ne dozvoljava


korisniku da definie posebnu boju, jer je dugme
Define Custom Colors deaktivirano. Podrazumevana
vrednost ovog svojstva je true.

FullOpen

Podeavanje svojstva FullOpen na true pre nego to


se dijalog prikae, automatski otvara dijalog sa
posebnim podeavanjima boja.

AnyColor

Postavljanjem ovog svojstva na true pokazuju nam se


sve dostupne boje u listi osnovnih boja.

CustomColors

Sa svojstvom CustomColors moete podesiti niz


posebnih boja, i moete proitati posebne boje koje
je korisnik podesio.

SolidColorOnly

Podeavanjem svojstva SolidColorOnly na


korisnik moe samo da izabere osnovne boje.

true,

38

Korienje kontrola za Windows


formulare I deo
Poslednjih godina Visual Basic pruao je programerima alate za kreiranje detaljnih korisnikih
interfejsa, kroz intuitivni dizajner formulara. Ovaj dizajner sa svojim alatima, zajedno sa
programskim jezikom lakim za uenje, predstavljao je moda najbolje okruenje za razvoj
velikih aplikacija. Jedna od stvari koje Visual Basic radi, kao i neki dragi alati za razvoj
aplikacija (npr. Delphi), jeste obezbeivanje pristupa predefinisanim kontrolama, koje
programer moe brzo ugraditi u korisniki interfejs aplikacije.
U centra veine Visual Basic Windows aplikacija nalazi se dizajner formulara. Korisniki
interfejs se kreira tako to se kontrole prevlae iz okvira za alate i sputaju na obrazac tamo
gde elimo da stoje kada se program izvrava. Dvostrukim pritiskom na kontrole dodaju se
ratine za obradu kontrola. Microsoftove unapred definisane kontrole, zajedno sa standardnim
kontrolama, koje se mogu kupiti po razumnim cenama, predstavljaju nov izvor potpuno
testiranog koda, koji se moe uvek koristiti. Ono to je bilo najvanije u Visual Basicu, sada
je, kroz Visual Studio .NET, dostupno C# programerima.
Veina kontrola korienih pre .NET-a bile su, i jo uvek jesu, specijalni COM objekti,
poznatiji kao ActiveX kontrole. Ove kontrole su se prikazivale i za vreme dizajniranja i za vreme
izvravanja programa. Svaka kontrola ima odreena svojstva, doputajui programeru
izvestan nivo prilagoavanja, kao to je podeavanje boje pozadine, naslova i njegove
pozicije u formulara. Kontrole koje emo videti u ovom predavanju izgledaju isto kao i ActiveX
kontrole, ali nisu - to su NET sklopovi. Ipak, i dalje se mogu koristiti kontrole dizajnirane za
starije verzije Visual Studija, iako produavaju rad zato to je potrebna dodatna obrada ovih
kontrola od strane .NET-a. Iz oiglednih razloga, kada je .NET dizajniran, Microsoft nije hteo
da napravi suvinim postojee kontrole, ve je pronaao nain da se i one upotrebe i pored
toga to e sve budue kontrole biti iste .NET komponente.
Ovi .NET sklopovi mogu biti dizajnirani tako da se koriste u bilo kojem od jezika Visual Studio.
U budunosti, veruje se, proizvodie se samo iste .NET komponente.
Ve smo imali prilike da vidimo dizajner formulara, nakratko, u ovoj knjizi. U ovom
predavanju detaljnije emo razmatrati dizajner, kao i izvestan broj kontrola iz okvira Visual
Studio .NET-a. Predstaviti sve kontrole trenutno prisutne u Visual Studio .NET-u, bilo bi
isuvie za ovu knjigu; zato emo predstaviti samo one najee koriene, poevi od oznaka
i okvira za tekst, do prikaza lista i statusnih linija.

Dizajner Windows formulara


Poeemo kratkim pregledom Windows dizajnera formulara. Ovo je centralno mesto za
kreiranje korisnikog interfejsa. Potpuno je mogue kreirati formulare bez korienja Visual
Studio .NET-a; meutim, dizajniranje interfejsa u Notepadu moe biti teak posao.
Da ponemo od okruenja u kojem emo raditi. Pokrenite Visual Studio .NET i kreirajte novi
C# Windows Application projekat tako to ete izabrati File | New | Project. U okviru za
dijalog koji se pojavljuje, u stablu sa leve strane pritisnite Visual C# Projects, a zatim
izaberite Windows Application u listi sa desne strane. 2a sada ne menjajte ime koje je
predloio Visual Studio i pritisnite OK. To bi trebalo da kreira prozor slian ovome ispod:

Ako ste upoznati sa dizajnerom formulara iz Visual Basica, primetiete odreene slinosti dizajner se pokazao kao dobro orue i neko je odluio da ga koriste i drugi jezici Visual
Studija. Ako niste upoznati sa dizajnerom, razmotrimo ta se sve pojavljuje na ovom
prozoru, panel po panel.
U centru samog prozora nalazi se formular koji dizajniramo. Kontrole se mogu prevlaiti iz
okvira sa alatima i sputati na formular. Okvir sa alatima se trenutno ne vidi na slici iznad.
Ali, al pomerite pokaziva mia skroz ulevo, iznad jezika kartice Toolbox, pojavie se.
Moete da pritisnete pribadau u gornjem desnom uglu panela da ga otvorite". Ovo e
prearanirati izgled radnog prostora, tako da se okvir sa alatima uvek vidi i nee smetati
samoj formi. Uskoro emo pogledati sam okvir sa alatima i ta sve on sadri.
Takoe skriven, na levoj traci, nalazi se i Server Explorera - predstavljen ikonama na
kojoj su nacrtani raunari, iznad jezika kartice Toolbox. Ovo se moe posmatrati i kao
kraa verzija Windows Control Panela. Odavde moete pretraivati mreu, dodavati ili
uklanjati veze sa bazama podataka i jo mnogo toga drugog.
Sa desne strane prozora nalaze se dva panela. Gornji je Solution Explorer i pregled klasa.
U Solution Exploreru moete videti sve otvorene projekte i njihove pridruene datoteke.
Ako pritisnete na karticu pri dnu Solution Explorera, aktivirate Class Viewer (pregled klasa).
Ovde moete pregledati sve klase koriene u projektima, kao i sve izvedene klase.
U donjem desnom delu prozora nalazi se panel Properties. Ovaj panel sadri sva svojstva
izabranog objekta, koja se lako mogu proitati ili izmeniti, tj. dopuniti. Cesto emo koristiti
ovaj panel u ovom predavanju.
Takoe, u ovom panelu vidi se i kartica Dynamic Help. Ovde se prikazuju svi saveti i uputstva
za izabrani objekat ili kod, ak i dok kucate. Ako imate stariji raunar sa malom koliinom
radne memorije, predlaemo da uklonite ovaj panel kada on nije potreban, zato to
aktivna potraga saveta i pomoi moe usporiti rad raunara.

Okvir sa alatima
Pogledajmo malo bolje okvir sa alatima - Toolbox. Ako ve to niste uradili, pomerite
pokaziva mia do okvira na levoj strani ekrana, i pritisnite pin u gornjem desnom uglu
panela, tako da ceo panel bude vidljiv.
Ako sluajno pritisnete X umesto pribadae i tako uklonite okvir sa alatima, moete ga ponovo vratiti u
prozor. Izaberite Toolbox iz menija View, ili pritisnite tastere Ctrl+Alt+X

Okvir sa alatima sadri sve kontrole dostupne .NET programerima. to je vanije, okvir sadri
sve kontrole za programere Windows aplikacija. Da ste izabrali kreiranje projekta Web
Forms, umesto projekta Windows Application, dobili biste drugi okvir sa alatima. Niste
obavezni da koristite ovakav izbor kontrola. Okvir sa alatima moete prilagoditi svojim
potrebama, ali u ovom predavanju fokusiraemo se na kontrole koje se nalaze u okviru (slika
iznad). U stvari, pogledaemo veinu od njih.

Kontrole
Veina kontrola u .NET-u izvedene su iz klase System.Windows.Forms.Control. Ova klasa
definie osnovno funkcionisanje kontrola, zbog ega su mnogi dogaaji i osobine kontrola identini.
Mnoge od ovih klasa su osnovne klase za druge kontrole, kao to je to sluaj sa klasama Labeli
TextBoxBase:

Neke kontrole, koje se nazivaju korisnikim kontrolama, izvedene su iz druge klase:


System.Windows.Forms.UserControl. Ova klasa je izvedena iz klase Control i
omoguuje nam da kreiramo sopstvene kontrole. Takoe, kontrole koje koristimo za
dizajniranje Web korisnikog interfejsa izvedene su iz klase
System.Web.UI.Control.

Osobine
Sve kontrole imaju odreene osobine koje odreuju kako e se neka kontrola ponaati. Osnova
klasa za veinu kontrola, Control, sadri odreen broj svojstava koje kontrole ili direktno
nasleuju, ili redefiniu u sluaju da se eli neko drugaije ponaanje kontrole.
Tabela ispod pokazuje najvanije osobine klase Control. Ove osobine bie prisutne u veini
kontrola koje demo videti u ovom predavanju. Zbog toga ih neemo ponovo detaljno objanjavati,
osim ukoliko ne menjamo ponaanje konkretne kontrole. Tabela nije napisana da zamori itaoca;
ukoliko elite da pronaete sve osobine klase Control, pogledajte MSDN biblioteku.
Ime osobine

Dostupnost

Opis

Anchor

itanje/upis

Ovo svojstvo definie ponaanje kontrole kada kontejner koji sadri


kontrolu menja svoju veliinu. Posle tabele nalazi se detaljno objanjenje
ove osobine.

BackColor

itanje/upis

Boja pozadine kontrole.

Bottom

itanje/upis

Dock

itanje/upis

Enabled

itanje/upis

Podesiti svojstvo Enabled na true (tano) obino znai da kontrola moe


da primi unos od strane korisnika. Podeeno na false (netano) obino
znai da ne moe.

ForeColor

itanje/upis

Boja prednjeg plana kontrole.

Height

itanje/upis

Udaljenost od vrha do dna kontrole.

Odreuje razdaljinu od vrha prozora do dna kontrole. Ovo nije isto to i


visina kontrole.
Doputa da kontrola bude pripojena uz ivicu prozora. Posle tabele nalazi
se detaljno objanjenje ove osobine.

Ime osobine

Dostupnost

Opis

Left

itanje/upis

Udaljenost leve ivice kontrole od leve ivice prozora.

Name

itanje/upis

Ime kontrole. Ime se koristi za pristup kontroli u kodu.

Parent

itanje/upis

Roditelj kontrole.

Right

itanje/upis

Udaljenost desne ivice kontrole od leve ivice prozora.

TabIndex

itanje/upis

Redosled promene kontrola u kontejneru koji ih dri prilikom pritiska na


taster Tab.

Tabstop

itanje/upis

Odreuje da li kontrola moe biti dostupna pritiskanjem tastera Tab.

Tag

itanje/upis

Ovu vrednost ne koristi sama kontrola, ve slui programerima za


smetanje informacija o kontroli. Ovoj osobini moe se dodeliti jedino
vrednost u formi stringa.

Top

itanje/upis

Udaljenost gornje ivice kontrole od vrha prozora.

Visible

itanje/upis

Odreuje da li je kontrola vidljiva u toku izvravanja programa.

Width

itanje/upis

irina kontrole.

Svojstva Anchor i Dock


Ove dve osobine su naroito korisne kada dizajnirate obrazac. Osigurati da prozor
normalno izgleda posle promene veliine prozora, nije nimalo lako. Ogroman broj redova
koda napisan je da bi se ovo moglo izvesti. Mnogi programi reavaju ovaj problem tako to ne
dozvoljavaju da se menja veliina prozora, to je svakako najlaki nain, ali ne i najbolji.
Svojstva Anchor i Dock, koja su uvedena kroz .NET okruenje, omoguavaju vam da reite
ovaj problem bez pisanja koda,
Svojstvo Anchor odreuje kako se kontrola ponaa kada korisnik promeni veliinu prozora u
kojem se kontrola nalazi. Moe se namestiti tako da i kontrola menja veliinu, zajedno sa
prozorom, ili da ostane iste veliine i na istom odstojanju od ivice prozora.
Svojstvo Dock je povezano sa svojstvom Anchor. Odreuje da li kontrola treba da bude
pripojena uz ivicu prozora kojem pripada. Ukoliko korisnik promeni veliinu prozora, kontrola
e i dalje biti pripojena uz ivicu. Ako, na primer, odredite da kontrola treba uvek da bude
pripojena uz donju ivicu prozora, kontrola e menjati svoju veliinu i ostati u donjem delu,
bez obzira na to kako menjate veliinu samog prozora.
Pogledajte primer okvira za tekst, kasnije u ovom predavanju, za tanu primenu Anchor
osobine,

Dogaaji
Kada korisnik programa pritisne dugme ili taster, programer bi hteo da zna da se to zaista
desilo. Da bi ovo bilo mogue, kontrole koriste dogaaje. Klasa Control definie brojne
dogaaje koji su zajedniki za kontrole. Tabela ispod opisuje neke od ovih dogaaja. Ovo je,
kao i ranije, izbor najee korienih; ukoliko elite da pronaete celu listu dogaaja,
pogledajte MSDN biblioteku.

Ime dogaaja

Opis

Click

Deava se kada se pritisne na kontrolu. Ovaj dogaaj e se takoe desiti kada se


pritisne taster Enter.

Doubleclick

Deava se kada se kontrola dva puta pritisne. Obradom dogaaja nekim


kontrolama, kao to je kontrola Button, znai da Doubleclick dogaaj nikad nee
biti pozvan.

DragDrop

Deava se kada se zavri operacija prevlaenja i sputanja. Drugim reima, kada


se neki objekat prevue do kontrole, a onda se pusti taster mia.

DragEnter

Deava se kada dovueni objekat ude u granice kontrole.

DragLeave

Deava se kada dovueni objekat naputa granice kontrole.

DragOver

Deava se kada dovueni objekat prelazi preko kontrole.

KeyDown

Deava se kada se taster pritisne dok kontrola ima fokus. Ovaj dogaaj uvek ide
pre dogaaja KeyPress i KeyUp.

Key Press

Deava se kada se taster pritisne dok kontrola ima fokus. Ovaj dogaaj uvek ide
posle KeyDown, a pre KeyUp dogaaja. Razlika izmeu KeyDown i KeyPress jeste
ta da KeyDown prenosi kod tastature za taster koji je pritisnut, dok KeyPress
prenosi odgovarajuu vrednost tipa char za taster.

KeyUp

Deava se kada se taster pusti dok kontrola ima fokus. Ovaj dogaaj uvek ide
posle dogaaja KeyDown i KeyPress.

GotFocus

Deava se kada kontrola primi fokus. Nemojte koristiti ovaj dogaaj za validaciju
kontrole - umesto toga koristite dogaaje Validating ili Validated.

LostFocus

Deava se kada kontrola izgubi fokus. Nemojte koristiti ovaj dogaaj za validaciju
kontrole - umesto toga koristite Validating ili Validated dogaaje.

MouseDown

Deava se kada se pokaziva mia nalazi iznad kontrole i kada se taster mia
pritisne. Ovo nije isto to i dogaaj Click; MouseDown se deava im se pritisne
dugme i pre nego to se pusti.

MouseMove

Deava se kontinuirano dok mi prelazi preko kontrole.

MouseUp

Deava se kada je pokaziva mia na kontroli i kada se taster mia oslobodi.

Paint

Deava se kada se kontrola iscrtava.

Validated

Ovaj dogaaj se deava kada se kontrola sa CausesValidation osobinom


podeenom na true, sprema da primi fokus. Poinje kada se zavri dogaaj
Validating i pokazuje da je validacija zavrena.

Validating

Ovaj dogaaj se deava kada se kontrola sa CausesValidation osobinom


podeenom na true, sprema da primi fokus. Kontrola nad ijim sadrajem se vri
validacija jeste ona kontrola koja gubi fokus, a ne ona koja ga prima.

Sada moemo da preemo na same kontrole i poeemo sa jednom koju smo videli u prethodnim
predavanju, kontrolom Button.

Kontrola Button
Kada se kae dugme (Button), verovatno pomislite na etvorougaono dugme koje se moe
pritisnuti radi izvoenja neke radnje. Meutim, tehniki, postoje tri vrste dugmadi u Visual
Studio .NET-u. To je zato to su radio-dugmad i polja za potvrdu, takoe dugmad. Zbog ovoga,
klasa Button nije direktno izvedena iz klase Control, ve iz klase ButtonBase, koja je
izvedena iz Control. Fokusiraemo se na kontrolu Button, a radio-dugme i polje za potvrdu
ostaviti za kasnije.
6

Kontrola Button postoji na svakom okviru za dijalog kojeg moete da se setite. Button se,
uglavnom, koristi za obavljanje tri vrste zadataka:
Za zatvaranje okvira za dijalog (npr. OK ili Cancel dugme);
Za izvravanje neke akcije nad podacima unetim u okviru za dijalog (npr. pritisak na dugme
Search posle unoenja nekog kriterijuma pretrage);
Za otvaranje nekog drugog okvira za dijalog ili aplikacije (npr. dugme Help).

Rad sa kontrolom Button je veoma jednostavan. Obino se sastoji od stavljanja kontrole u


formular, dvostrukog pritiska na kontrolu za dodavanje koda za dogaaj Click, to e bid
dovoljno za veinu aplikacija sa kojima ete radio.
Razmotrimo sada neke najee koriene osobine i dogaaje kontrole. To e vam omoguiti
da shvatite ta se sve moe uraditi sa kontrolom. Zatim, napraviemo mali primer koji
e demonstrirati neke od osnovnih svojstava i dogaaja dugmeta

Svojstva kontrole Button


Opisaemo osobine kao lanove klase Button, iako su, tehniki, ove osobine definisane u
klasi ButtonBase. Samo one najee koriene opisane su u tabeli. Za celu listu,
pogledajte MSDN biblioteku.
Ime osobine

Dostupnost

Opis

itanje/upis

Izgled dugmeta moe biti izmenjen pomou ove osobine. Ako


namestite stil na PopUp, dugme e biti ravno sve dok se pokaziva
mia ne pomeri na njega. Tada se dugme pojavljuje u
normalnom, 3D obliku.

Enabled

itanje/upis

Pominjemo ovu osobinu ovde, iako je ona izvedena iz klase Control,


zato to je od velike vanosti za dugme. Podeavanje Enabled
osobine na false znai da dugme postaje sivo i nita se ne deava
kada se pritisne na njega.

Image

itanje/upis

Omoguava biranje slike (bitmape, ikone itd.) koja e se pojaviti na


dugmetu.

ImageAlign

itanje/upis

Uz pomo ove osobine moete da izaberete poloaj slike na


dugmetu.

FlatStyle

Dogaaji kontrole Button


Daleko najkorieniji dogaaj dugmeta jeste dogaaj Click. Deava se kada korisnik pritisne
na dugme; pod ovim se misli kada pritisne levo dugme mia i kada ga oslobodi dok se pokaziva
mia nalazi na dugmetu. To znai da kada pritisnete levim dugmetom mia, a zatim pomerite
pokaziva mia sa kontrole pre nego to oslobodite levo dugme mia, nee doi do
dogaaja Click. Takoe, do dogaaja Click dolazi kada je dugme u fokusu i kada korisnik
pritisne taster Enter. Ako imate dugme na formularu, uvek treba obraditi ovaj dogaaj.
Preimo sada na primer. Kreiraemo dijalog sa tri dugmeta. Dva e menjati korieni jezik sa
engleskog na danski i obrnuto (moete da koristite bilo koji drugi jezik). Poslednje dugme e
zatvarati dijalog.

Primer kontrole Button

Veba br. 21.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:

1. Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Windows Application u okviru prozora Templates: U okviru za tekst Location:
promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba21 (ovaj e direktorijum
biti automatski napravljen ukoliko ve ne postoji), i ostavite podrazumevani tekst u
okviru za tekst Name: Kontrola Button.
2. Otvorite paletu Properties i za kontrolu forme podesite sledee osobine:
Osobina (Properties)
Name
Text
StartPosition
Font
FormBorderStyle
Size

Vrednost (Value)
fclsMain
Kontrola Button
CenterScreen
Microsoft Sans Serif, Regular, 8, Central
European
FixedSingle
262; 150

Napomena:
Vodite rauna o konvenciji imenovanja kontrola, kao to je prikazano u lekciji Imenovanje kontrola,
promenljivih i konvencijama pisanja programa.
3. Probajte odmah posle da startujete aplikaciju,
pritiskajui na tastaturi taster F5. Dobiete
poruku o greki. Slino ovoj.

4. Takoe u okviru prozora Task List generisae se poruka o greci. Kliknite dva puta na datu
greku i Visual Studio .NET e nas odvesti do greke u kodu.

5. Poto smo promenuli ime kontrole forme, moraemo runo promenuti i naziv fome u u
samom kodu. Dakle umesto dotinog naziva Form1 postavite:

Napomena:
Ovo preimenovanje se mora svaki put uraditi samo kod kontrole forme jer Visual Studio .NET
sam to ne radi, kao to to radi Programski jezik Delphi. Kod ostalih kontrole naravno to nije
potrebno sam VS to radi umesto nas.
6. Pokrenimo ponovo aplikaciju sa F5.
7. Otvorite okvir sa alatima (Toolbar) i tri puta dvostruko pritisnite kontrolu Button.
Postaviemo tri kontrole dugmeta na samu formu Button1, Button2, Button3. Podesite
sledee osobine redom za kontrole dugmad.
za Button1
Osobina (Properties)
Name
Text
Cursor
Image
ImageAlign
Location
Size

Vrednost (Value)
btnEngleski
&Engleski
Hand
C:\Program Files \M ic r os oft Visual Sudio
.NET\Common7\Graphics\icons\Flags\ flguk.ico
BottomLeft
16; 24
96; 23

za Button2
Osobina (Properties)
Name
Text
Cursor
Image
ImageAlign
Location
Size

Vrednost (Value)
btnDanski
&Danski
Hand
C:\Program Files \M ic r os oft Visual Sudio
.NET\Common7\Graphics\icons\Flags\ flgden.ico
BottomLeft
144; 24
96; 23

za Button3
Osobina (Properties)
Name
Text
Cursor
Location
Size

Vrednost (Value)
btnOk
&OK
Hand
88; 72
75; 23

Trebalo bi da dobijemo izgled forme kao na slici:

8. Sada moramo da unesemo ta e aplikacija da radi. Odnosno treba da unesemo kod.


Za kontrolu btnEngleski. To se moe uraditi na dva naina. Prvi tako to dva puta
kliknete na dugme btnEngleski i VS e sam napraviti dogaaj Click. Drugi nain je
preko okvira prozora Events i dvaput kliktanjem na dogaaj Click. Unesite sledei
kod u telu Click dogaaja.

To isto uradite i sa btnDanski.

Na kraju to isto uradite i za dugme btnOk.

9. Na kraju pokrenite sa F5 aplikaciju i isprobajte je.

10

Kontrole Label i LinkLabel


Kontrola Label se moda najee koristi od svih kontrola. Pogledajte bilo koju Windows
aplikaciju, i nai ete ovu kontrolu u skoro svakom dijalogu.
Visual Studio .NET sadri dve kontrole za oznake, koje se predstavljaju korisnicima na
dva razliita naina;
Label, standardna Windows oznaka;
LinkLabel, oznaka slina standardnoj (i izvedena iz nje), ali predstavlja sebe kao
internet vezu (hiperveza).
Obe kontrole nalaze se na vrhu kartice Windows Forms. Na slici koja sledi ubaene su obe
oznake, da biste videli razliku medu njima.
Ako imate iskustva sa Visual Basicom, primeujete da se za prikazivanje teksta koristi svojstvo Text, a
ne svojstvo Caption. Videete da sve .NET kontrole koriste svojstvo Text za unos teksta koji
opisuje kontrolu. Pre .NET-a, svojstva Caption i Text su se upotrebljavala u iste svrhe.

Ovo je otprilike sve to se tie korienja kontrola Label. Obino ne morate dodavati nikakav
upravljaki kod za dogaaje, kada je u pitanju standardna labela. U sluaju kontrole LinkLabel,
potreban je dodatni kod ako elite da omoguite korisniku da pritisne na ovu oznaku, to e mu
omoguiti otvaranje Web stranice.
Kontrola Label ima iznenaujui broj svojstava koje se mogu podeavati. Veina njih je izvedena iz
klase Control, ali postoje i neke nove. Tabela koja sledi opisuje najee koriene. Ako
drugaije nije naznaeno, svojstvo vai i za kontrolu Label i za LinkLabel:
Ime osobine

Dostupnost

Opis

BorderStyle

itanje/upis

Omoguava da izaberete date ivice oznake. Podrazumeva se da nema


ivica.

DisabledLinkColor

itanje/upis

Samo za LinkLabel: boja koju e kontrola LinkLabel imati kada je


korisnik pritisne.

FlatStyle

itanje/upis

Definie izgled kontrole. Ako podesite ovu osobinu na PopUp, kontrola


e biti ravna sve dok pokaziva mia ne pomerite na kontrolu. Tada e
se kontrola izdii.

Image

itanje/upis

Omoguava biranje slike (bitmape, ikone itd.) koja e se pojaviti na


oznaci.

ImageAlign

itanje/upis

Odreuje poloaj slike na oznaci.

LinkArea

itanje/upis

Samo za LinkLabel: opseg teksta koji e biti prikazan kao veza.

LinkColor

itanje/upis

Samo za LinkLabel: Boja hiperveze.

Links

itanje/upis

Samo za LinkLabel: kontrola LinkLabel moe da dri vise od jedne


veze. Ovo svojstvo omoguava vam da pronaete vezu koju hoete.
Kontrola vodi rauna o vezama koje se nalaze u tekstu.

LinkVisited

itanje/upis

Samo za LinkLabel: obavetava da li je neka hiperveza prethodno


poseena ili ne.

Text

itanje/upis

Tekst koji se pojavljuje u oznaci.

TextAlign

itanje/upis

Odreuje poloaj teksta na kontroli.

11

Kontrola TextBox
Okvir za tekst trebalo bi da bude korien kada oekujete od korisnika unos teksta, o
kojem ne znate nita u toku dizajniranja programa (npr. ime korisnika). Osnovna funkcija
okvira za tekst jeste da omogui korisniku da unese tekst, pri emu se moe uneti bilo
koji znak i sasvim je mogue primorati korisnika da unese samo numerike vrednosti.
U .NET okruenju postoje dve osnovne kontrole koje mogu primati tekst kao ulazni
podatak: TextBox i RichTextBox (o kontroli RichTextBox priaemo kasnije u ovom
predavanju). Obe kontrole izvedene su iz klase TextBoxBase, koja je izvedena iz klase
Control.
Klasa TextBoxBase omoguava osnovnu funkcionalnost za obradu teksta u okvirima za
tekst, kao to su izbor, isecanje i kopiranje teksta, kao i veliki broj dogaaja. Neemo se
sada mnogo baviti posledicama, ve demo pogledati jednostavniju od dve kontrole TextBox. Uradiemo primer da demonstriramo osobine kontrole TextBox, a kasnije
dopuniti taj primer i pokazati kontrolu RichTextBox.

Svojstva kontrole TextBox

Kao to ve znate, postoji jako mnogo svojstava. Ponovo demo navesti samo one
najvanije:
Ime osobine

Dostupnost

Opis

Causes Validation

itanje/upis

Odreuje da li e kontrola TextBox menjati slova u mala ili velika.


Mogue vrednosti su: Lower: sva uneta slova bie konvertovana u mala
slova.

CharacterCasing

itanje/upis

Q Normal: nee biti nikakvih promena.

MaxLength

itanje/upis

Upper: sva uneta slova bide konvertovana u velika slova.


Vrednost koja odreuje maksimalan broj karaktera u tekstu koji je
unet u TextBox. Podesite ovu vrednost na nulu ako je maksimum
ogranien samo raspoloivom memorijom.

MultiLine

itanje/upis

Pokazuje da li je ovo kontrola sa vise redova. Kontrola sa vise redova


moe da prikae vise redova teksta.

PasswordChar

itanje/upis

Odreuje da li karakter lozinke treba da zameni stvarne karaktere koji su


uneti u okvir za tekst sa jednim redom. Ako je svojstvo Multiline
postavljeno na true, tada ovo svojstvo nema nikakvog efekta.

Readonly

itanje/upis

Logika vrednost koja pokazuje da li je tekst samo za itanje.

ScrollBars

itanje/upis

Odreuje da li tekst u vise redova treba da ima traku za pomeranje.

SelectedText

itanje/upis

Tekst koji je izabran u okviru za tekst.

itanje/upis

Broj izabranih karaktera u tekstu. Ako je ova vrednost vea od ukupnog


broja karaktera u tekstu, onda kontrola resetuje ovu vrednost na ukupan
broj karaktera, minus vrednost koja se nalazi u svojstvu
SelectionStart.

SelectionLength
SelectionStart

Poetak izabranog teksta u okviru za tekst.

Wordwrap

Odreuje da li u okvirima za tekst sa vise redova, re koja premauje irinu


kontrole treba automatski da bude prebaena u novi red.

12

Dogaaji kontrole TextBox


Paljiva provera ispravnosti teksta, koji se unosi u kontrolu TextBox, moe da napravi razliku
izmeu zadovoljnih i veoma ljutih korisnika.
Verovatno ste iskusili koliko iritirajue moe biti kada dijalog proverava ispravnost svog sadraja tek
kada pritisnete OK. Ovaj nain provere ispravnosti podataka obino za posledicu ima
pojavljivanje poruke da su podaci u kontroli TextBox broj tri" neispravni. Tada moete
nastaviti da pritiskate OK sve dok svi podaci ne postanu korektni. Oigledno, ovo nije dobar nain
provere ispravnosti podataka. Dakle, ta se moe uiniti po ovom pitanju?
Odgovor lei u obradi dogaaja za proveru ispravnosti, koji obezbeuje kontrola TextBox. Ako elite
da budete sigurni da se ne unose nedozvoljeni karakteri ili da su doputeni samo karakteri iz
odreenog opsega, onda ete hteti da korisnik kontrole bude obaveten da li je uneti karakter
ispravan ili nije.
Kontrola TextBox obezbeuje ove dogaaje (koji su svi izvedeni iz klase Control):
Ime dogaaja
Enter
GotFocus
Leave
Validating
Validated

Opis
Ovih est dogaaja deavaju se redom kojim su ovde navedeni. Poznati su kao
dogaaji fokusa" i aktiviraju se uvek kada se menja fokus kontrole, uz dva
izuzetka. Dogaaji Validating i Validated deavaju se samo kada
kontrola koja prima fokus, ima svojstvo CausesValidation podeeno na
true. Razlog da se dogaaj vee za kontrolu koja prima fokus, jeste taj to
nekad ne elite proveru ispravnosti sadraja kontrole, ak i kada se fokus menja.
Primer za ovo je kada korisnik pritisne Help dugme.

LostFocus
KeyDown
KeyPress
KeyUp
Change

Sledea tri dogaaja su poznatija kao taster dogaaj. Oni omoguavaju da


pratite i menjate ono to je uneto u kontrolu.
KeyDown i KeyUp primaju kod tastera koji je pritisnut. Na ovaj nain moete
videti da li su pritisnuti specijalni tasteri, kao sto su Shift, Control ili F1.
KeyPress, sa druge strane, prima karakter koji odgovara tastera. To znai da
vrednost za slovo a" nije ista kao i za slovo Ovo moe biti korisno ako elite da
ograniite opseg karaktera, npr. omoguavanjem unosa samo numerikih
karaktera.
Deava se uvek kada se tekst u okviru za tekst menja, bez obzira na vrstu
promene.

Primer kontrole TextBox

Veba br. 22.


Kreiraemo dijalog u okviru koga moete da unesete svoje ime, adresu, zanimanje i godine starosti.
Svrha ovog primera jeste da vas pripremi za korienje svojstava i dogaaja, a ne da kreira neto veoma
korisno.
Prvo emo napraviti korisniki interfejs:
1. Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Windows Application u okviru prozora Templates: U okviru za tekst Location: promenite
putanju u C:\Temp\SoftIng\LecturesCode\Vezba22 (ovaj e direktorijum biti automatski
napravljen ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst
Name: PrimerTextBox.
2. Napravite formular, kao na slici koja sledi, dodavanjem oznaka, okvira za tekst i dugmeta. Pre
nego to promenite veliinu okvira za tekst - txtAddress i txtOutput ~ kao sto je pokazano,
morate da podesite njihova svojstva Multiline na true. Ovo ete uraditi desnim pritiskom
na kontrole i biranjem Properties:
13

3. Kontrole nazovite kao to je prikazano u tabelama.


za Form1
Osobina (Properties)
Name
Text
Font
FormBorderStyle
StartPosition
Size

Vrednost (Value)
fclsMain
Primer TextBox-a
Microsoft Sans Serif, Regular, 8, Central European
FixedSingle
CenterScreen
520; 432

pet kontrola TextBox, redom:


za TextBox1
Osobina (Properties)
Name
Text
Multiline
Location
Size

Vrednost (Value)
txtIme
False
104; 16
296; 20

14

za TextBox2
Osobina (Properties)
Name
Text
Multiline
ScrollBars
Location
Size

Vrednost (Value)
txtAdresa
True
Vertical
104; 46
296; 136

za TextBox3
Osobina (Properties)
Name
Text
Multiline
Location
Size

Vrednost (Value)
txtZanimanje
False
104; 192
296; 20

za TextBox4
Osobina (Properties)
Name
Text
Multiline
Location
Size

Vrednost (Value)
txtGodiste
False
104; 222
72; 20

za TextBox5
Osobina (Properties)
Name
Text
Multiline
ReadOnly
ScrollBars
Location
Size

Vrednost (Value)
txtIzlaz
True
True
Vertical
0; 296
512; 104

Pored njih 5 kontrola Label-a, kao to je prikazano na prethodnoj slici.


Zatim na formu postavite tri dugmeta odnosno kontrole Button, redom:

15

za Button1
Osobina (Properties)
Name
Text
Cursor
Location
Size

Vrednost (Value)
btnOK
&OK
Hand
415; 16
75; 23

za Button2
Osobina (Properties)
Name
Text
Cursor
CausesValidation
Location
Size

Vrednost (Value)
btnHelp
&Help
Hand
false
415; 48
75; 23

za Button3
Osobina (Properties)
Name
Text
Cursor
Location
Size

Vrednost (Value)
btnIzlaz
&Izlaz
Hand
416; 128
75; 23

Setite se iz razmatranja dogaaja Validating i Validate da podeavanje ove osobine na false


doputa korisniku da pritisne na dugme, a da ne mora da brine o ispravnosti podataka.
Kad smo podesili dimenzije forme, i na njoj kontrole, podesimo svojstvo Anchor kontrola tako da
se kontrole ponaaju normalno kada menjamo veliinu formulara (naravno, ako vratimo osobinu
forme FormBorderStyle na Sizable). Podesite svojstvo Anchor kao to je prikazano u tabeli koja
sledi:
Kontrola
Sve oznake labele
Svi okviri za tekst- TextBox-ove
osim txtAdresa
Tri dugmeta - Button

Anchor vrednost
Top, Left
Top, Bottom, Left, Right
Top, Left, Right
Top, Right

Savet: Tekst koji opisuje svojstvo Anchor moete kopirati iz jedne kontrole u drugu; na taj nain
kopirate i vrednosti osobine. Ovako ne morate koristiti padajui meni.

Razlog zbog kojeg je kontrola txtOutput stavljena na dno formulara (Anchor), a ne pripojena uz
ivicu (Dock), jeste taj to elimo da ovaj prostor za prikaz unetog teksta menja svoju veliinu
zajedno sa promenom veliine formulara. Da smo kontrolu pripojili donjoj ivici formulara pri
16

promeni veliine formulara, kontrola bi uvek ostajala pripojena ivici, ali njena veliina ne bi bila
promenjena.
Ako smo vratili osobinu forme FormBorderStyle na Sizable onda bi trebalo da podesimo osobine
Size i MinSize. Ne bi imalo smisla da formular bude manji nego to je sada. Stoga, podesite da
svojstvo MinSize bude isto kao svojstvo Size.
Podeavanje izgleda formulara ovim je zavreno. Ako pokrenete ovaj program, nita se ne
deava kada pritisnete na neko dugme ili ukucate neki tekst. Ali, ako poveate veliinu
formulara ili je povuete, primetiete da se kontrole ponaaju ba onako kako smo hteli - ostaju
u eljenom poloaju i odgovarajuoj razmeri. Ako ste ikada pokuali da obavite isti zadatak u
jeziku kao to je Visual Basic 6, znate koliki ste trud upravo utedeli.
Sada je vreme da predemo na kod. Pritisnite desnim tasterom mia formular i izaberite View
Code. Ako imate prikazan okvir sa alatima, trebalo bi da ga sklonite da biste dobili vise mesta za
prozor sa kodom.
Iznenaujue malo koda se pojavljuje u programu za ureivanje. Na vrhu nae klase su
definisane kontrole, ali tek kada proirite oblast pod oznakom Windows Form Designer
Generated Code, moete da vidite ta ste sve do sada uradili. Ovaj kod nikada ne bi trebalo da
menjate! Sledei put kada neto promenite u dizajneru, novi k6d e biti upisan preko
postojeeg, ili, jo gore, moete napraviti takvu izmenu da dizajner vise ne pokazuje va
formular.
Posvetite malo vremena iskazima koji se nalaze u ovoj oblasti. Shvatiete zato je mogue
kreirati Windows aplikaciju bez korienja Visual Studio .NET-a. Sve to se ovde nalazi
jednostavno je moglo biti kreirano i u Notepadu ili nekom drugom programu za ureivanje
teksta.
Takoe, videete zato se ovo ne preporuuje. Voditi rauna o svemu to vidite je teko; lako se
potkradaju greke i, zbog toga to ne moete da vidite efekte onoga to radite, smetanje
kontrola na formular na pravi nain predstavlja naporan posao. Ovo, meutim, daje ansu nekim
drugim proizvoaima softvera za pisanje sopstvenog programerskog okruenja konkurentskog
Visual Studio .NET-u, zbog toga to su kompajleri, koji se koriste za kreiranje formulara, sastavni
deo .NET okruenja, a ne Visual Studio .NET-a.

17

Dodavanje rutina za obradu dogaaja


Moemo jo malo iskoristiti dizajner formulara, pre nego to dodamo na kod. Vratite se
dizajner formulara (pritiskom na jeziak kartice u vrhu programa za ureivanje teksta), i
dvaput pritisnite dugme btnOK. Ponovite ovo i sa drugim dugmetom. Kao to smo ve videli iz
primera za dugme, dvostruki pritisak na dugme kreira rutinu za obradu dogaaja Click. Kada
se pritisne na OK dugme, elimo da prebacimo tekst iz ulaznih okvira za tekst u izlazni okvir
koji je samo za itanje.
Ovo je kod za dva dogaaja Click:

U obe funkcije koristi se svojstvo Text okvira za tekst, bilo da se ita ili upisuje u funkciji
btnOK_Click (), ili da se samo upisuje u akciji btnHelp_Click () .
Ubacujemo informacije koje je korisnik uneo, bez provere njihove korektnosti. To znai da
proveru moramo raditi na nekom drugom mestu. U ovom primeru postoje odreeni kriterijumi
koji se moraju ispuniti, da bi podaci bili korektni:
Polje za ime korisnika ne moe biti prazno;
Broj godina korisnika mora biti vei ili jednak nuli;
Zanimanje korisnika mora biti Programer" ili ostavljeno prazno;
Polje za adresu korisnika ne moe biti prazno.
Ovde vidimo da su provere za dva okvira za tekst (txtName i txtAddress) iste. Takoe, moramo
spreiti korisnika da unese nevaei podatak u polju Age, i na kraju moramo proveriti da li je
korisnik programer.
Da bismo spreili korisnika da pritisne dugme OK, nego to je bilo ta uneto, podesiemo svojstvo
Enabled dugmeta OK na false u konstruktoru formulara, vodei rauna da u ovo svojstvo ne
upiemo vrednost true sve dok se ne pozove kod u metodu Initialize-Component().

18

Sada emo kreirati rutinu za obradu dogaaja za dva okvira za tekst, za koje moramo proveriti
da li su prazni. Ovo radimo korienjem dogaaja Validating za okvire. Kontrolu obavetavamo da
e dogaaj biti obraen u metodi pod imenom txtBoxEmpty_Validating ().
Takoe, trebalo bi da znamo status kontrola. Za ovo koristimo svojstvo Tag okvira za tekst. Ako
se seate, rekli smo da se, iz dizajnera formulara, svojstvu Tag mogu dodeliti samo stringovi.
Meutim, poto podeavamo svojstvo Tag iz koda, moemo uraditi bilo ta sa njim. Ovde je bolje
koristiti logiku vrednost.
U konstruktor dodajemo sledee iskaze:

Za razliku od rutina za obradu dogaaja dugmeta, koje smo ve videli, rutina za obradu dogaaja
Validating je specijalna verzija standardne ratine za obradu dogaaja System.Event-Handler.
Specijalna rutina za obradu dogaaja Validating treba nam zbog sluaja neispravnih podataka,
kada treba spreiti dalju obradu tih podataka. Kada bismo obustavili dalju obradu svih podataka,
to bi praktino znailo da bi bilo nemogue napustiti okvir za tekst sve dok se ne unesu ispravni
podaci. Neemo raditi nita tako drastino u ovom primeru.
Dogaaji Validating i Validate, zajedno sa svojstvom CausesValidation reavaju problem koji nastaje
korienjem dogaaja GotFocus i LostFocus za proveru ispravnosti sadraja kontrole. Problem nastaje
kada se dogaaji GotFocus i LostFocus neprestano aktiviraju, zbog toga sto kod za proveru ispravnosti
prebacuje fokus sa jedne na drugu kontrolu. To je stvaralo beskonanu petlju.

Dodajemo rutinu za obradu dogaaja:

19

Zato to vise okvira za tekst koriste ovaj metod za obradu dogaaja, ne moemo biti sigurni koji
okvir poziva funkciju. Ipak, znamo da efekat izvravanja ove funkcije treba uvek da bude isti,
bez obzira na to koji okvir poziva funkciju. Stoga, konvertujemo parametar sender u objekat tipa
TextBox i dalje nastavljamo da radimo na tom objektu.
Ako je duina teksta u okviru nula, podesimo boju pozadine na crveno i tag na false. Ako ne,
onda podesimo boju pozadine na standardnu Windows boju prozora.
Uvek koristiti boje iz enumeracije System.Drawing.SystemColors kada elite da podesite kontrolu na
standardnu boju. Ako podesite boju na belu, vaa aplikacija e izgledati udno u odnosu na ostale
aplikacije ako je korisnik promenio podrazumevane boje.

Funkcija ValidateAll () je opisana na kraju ovog primera


Nastavljamo sa dogaajem Validating dodajui rutinu za obradu kontroli txtZanimanje. Procedura
je ista kao za dve prethodne rutine, ali je kod drugaiji zato to zanimanje mora biti ili
Programer, ili ostavljeno prazno, da bi kontrola bila validna. Stoga, dodajemo novi red
konstruktoru:

20

Zatim, i rutinu za obradu:

Pretposlednji izazov je polje za godine starosti. Ne elimo da korisnik unosi nita drugo osim
pozitivnih brojeva (ukljuujui i nulu, da bi primer bio jednostavniji). Da bismo ovo postigli,
koristiemo dogaaj KeyPress za uklanjanje neeljenih znakova pre nego to se oni prikau u
okvira za tekst.
Prvo se prijavljujemo za dogaaj KeyPress, na slian nain kao i sa prethodnim rutinama - u
konstruktoru:

Rutina za obradu je takoe specijalna. Obezbeen je parametar System.Windows.Forms.


KeyPressEventHandler, zato to je dogadaju potrebna informacija o tome koji je taster pritisnut.
Dodajemo rutinu za obradu dogaaja:

ASCII vrednosti za cifre od 0 do 9 su u opsegu od 48 do 57. Ipak, pravimo jedan izuzetak. ASCII
vrednost 8 odnosi se na taster za brisanje (Backspace). Neophodno je dozvoliti i pritiskanje
tastera za brisanje ako elimo da dopustimo korisniku da ispravi netanu informaciju.

21

Podeavanjem svojstva Handled objekta KeyPressEventArgs na true, govorimo kontroli da ne radi


nita sa znakom; zbog toga znak nee bid prikazan.
Za sada, kontrola nije oznaena ni kao ispravna, ni kao neispravna. To je zato to nam treba jo
jedna provera da vidimo da li je ita uneto. S obzirom na to da ve imamo metodu za ovu
proveru, jednostavno prijavljujemo dogadaj Validating i za kontrolu Age, dodavanjem jo jedne
linije u konstruktor:

Ostaje jo jedna stvar o kojoj moramo da proverimo. Ako korisnik unese ispravne informacije u
sve okvire za tekst, a zatim napravi izmenu tako da neka informacija postane neispravna, dugme
OK ostaje dostupno. Dakle, moramo napisati poslednju rutinu za obradu dogaaja za sve
tekstualne okvire: dogaaj Change koji e dugme OK dugme uiniti nedostupnim ako bilo koje
polje za tekst sadri neispravne podatke.
Dogaaj Change aktivira se kad god se tekst u kontroli menja. Prijavljujemo dogaaj dodavanjem
sledeih redova konstruktoru:

Dogaaj Change koristi standardnu rutinu za obradu dogaaja, koja nam je poznata iz dogaaja
Click. Zatim dodajemo i sam dogaaj:

Ovoga puta moramo tano znati koja kontrola poziva ratinu za obradu dogaaja, zato to ne
elimo da se boja pozadine okvira Occupation promeni u crveno kada korisnik zapone kucanje.
22

Ovo postiemo proverom svojstva Name onog okvira koji je prosleen kroz parametar sender.
Jo jedna stvar ostaje: metoda ValidateAll() koja dugme OK ini dostupnim ili nedostupnim:

Ova metoda jednostavno podeava svojstvo Enabled za dugme OK na true, ako sva svojstva Tag
imaju vrednost true. Moramo vrednosti svojstava Tag konvertovati u logike vrednosti, zato to
je svojstvo Enabled logika promenljiva.
Ako isprobate program, trebalo bi da dobijete neto nalik ovome:

Primetiete da moete da pritisnete na dugme Help dok imate okvire za tekst sa neispravnim
podacima, bez promene boje pozadine u crveno.
Primer koji ste upravo zavrili jeste prilino veliki u odnosu na sledee primere iz ovog
predavanja. To je zato to emo ovaj primer koristiti za sve koji slede.

23

Korienje kontrola za Windows


forme II deo
Kontrole RadioButton i CheckBox

Kao to smo ve rekli, kontrole RadioButton i CheckBox koriste istu osnovnu klasu kao i kontrola
Button, iako im se izgled i korienje znamo razlikuju.
Radio dugme se tradicionalno prikazuje kao oznaka sa kruiem na levoj strani, koje moe biti
izabrano ili ne. Radio dugme bi trebalo koristiti kada elite od korisnika da bira izmeu
meusobno iskljuivih opcija. Primer za to bi mogao biti pol korisnika.
Da biste grupisali vise radio dugmadi kako bi ona inila logiku jedinicu, koristite kontrolu
GroupBox. Prvo stavite kontrolu GroupBox na formular, zatim ubacite neophodne kontrole
RadioButton unutar tog okvira; kontrole RadioButton znae kako da menjaju svoj status tako da
samo jedna kontrola unutar grupnog okvira bude izabrana. Ako kontrole RadioButton ne stavite u
grupni okvir, samo jedna od njih unutar formulara moe biti izabrana.
Kontrola CheckBox (polje za potvrdu) tradicionalno se predstavlja kao oznaka sa kvadratiem na
levoj strani, koji moe biti potvren. Koristite polja za potvrdu kada elite da omoguite
korisniku da bira jednu ili vise opcija. Primer moe biti upitnik gde korisnik bira operativne
sisteme koje je koristio (npr. Windows 95, Windows 98, Linux, Max OS X itd.).
Pogledaemo vanije osobine i dogaaje za ove dve kontrole, poevi od radio dugmeta, a zatim
pred na primere.

Svojstva kontrole RadioButton

Poto je kontrola izvedena is klase ButtonBase, a ve smo videli neke osobine kontrole Button,
ovde emo opisati samo nekoliko svojstava. Kao i uvek, ako vam je potrebna kompletna lista
svojstava, pogledajte MSDN biblioteku.
Ime osobine

Dostupnost

Opis

itanje/upis

Radio dugme se pojavljuje kao oznaka sa kruiem levo, u sredini


ili desno od oznake, ili kao standardno dugme. U poslednjem
sluaju, dugme se prikazuje kao pritisnuto ako je izabrano,
odnosno u 3D obliku ako nije.

AutoCheck

itanje/upis

Ako je ovo svojstvo podeena na true, znak za potvrivanje se


pojavljuje kada korisnik pritisne na radio dugme. Kada je ovo
svojstvo podeeno na false, podrazumeva se da se znak za
potvrivanje ne pojavljuje.

CheckAlign

itanje/upis

Odreuje poloaj radio dugmeta. Svojstvo moe biti podeeno na


left, middle ili right (levo, u sredini, desno).

Checked

itanje/upis

Pokazuje status kontrole. Ako je kontrola potvrena, onda je ovo


svojstvo podeeno na true, odnosno false u suprotnom.

Appearance

Dogaaji kontrole RadioButton

Obino, imaete samo jedan dogaaj kada radite sa kontrolama RadioButton. Naravno, postoje i
drugi dogaaji. Razmatraemo samo dva u ovom predavanju, a jedini razlog to pominjemo dragi
dogaaj jeste taj to postoji jedva primetna razlika koju treba istai:
Ime

Opis

CheckChanged

Ovaj dogaaj se alje kada se menja potvrda radio dugmeta. Ako


ima vise kontrola RadioButton na formularu ili unutar jednog
grupnog okvira, ovaj dogaaj se alje dva puta: prvo kontroli koja
je bila potvrena a sada vise nije, a zatim kontroli koja postaje
potvrena.

Click

Ovaj dogaaj se alje svaki put kada se pritisne na radio dugme.


Ovo nije isto kao i dogaaj CheckChanged, zato to pritisak na
radio dugme dva ili vise puta uzastopno menja svojstvo Checked
samo jednom - i to samo ako kontrola nije prethodno bila
potvrena.

Svojstva kontrole CheckBox

Kao to pretpostavljate, osobine i dogaaji ove kontrole su slini onima za RadioButton, ali tu su
i dve nove:
Ime osobine

Dostupnost

Opis

CheckState

itanje/upis

Za razliku od radio dugmeta, polje za potvrdu moe imati tri


statusa: Checked, Indeterminate i Unchecked (potvreno,
neodreeno i nepotvreno). Ako polje ima status Indeterminate,
onda je obino krui pored oznake siv, tako pokazujui da je
trenutna vrednost kruia ili neispravna ili nema nikakvog smisla u
trenutnim okolnostima. Primer ovakvog statusa moete videti ako
izaberete nekoliko datoteka u Windows Exploreru i pogledate
Properties ovih datoteka. Ako se neke od ovih datoteka mogu samo
itati, a druge i menjati i itati, onda e polje za potvrdu Readonly biti potvreno, ali sivo - neodreeno.

ThreeState

itanje/upis

Ako je ovo svojstvo podeena na false, korisnik nee modi da


izmeni status kontrole na Indeterminate. Moete, meutim,
izmeniti status u kodu.

Dogaaji kontrole CheckBox

Obino, koristiete samo jedan ili dva dogaaja za ovu kontrolu. Iako dogaaj CheckChanged
postoji i za kontrole RadioButton i CheckBox, javlja se izvesna razlika u efektima ovih dogaaja:
Ime

Opis

CheckedChanged

Deava se kada se menja svojstvo Checked kontrole. Kod kontrola


sa osobinom ThreeState podeenom na true mogue je pritisnuti
na polje za potvrdu bez promene Checked osobine. Do ovoga
dolazi kada se status polja menja iz Checked uIndeterminate.

CheckedStateChanged

Deava se kada se menja svojstvo CheckedState kontrole. Kako


su Checked i Unchecked mogue vrednosti za svojstvo
CheckedState, ovaj dogaaj e biti poslat uvek kada se menja
svojstvo Checked. Takoe, bie poslat kada se status menja iz
CheckeduIndeterminate.

Ovim zavravamo opise dogaaja i svojstava kontrola RadioButton i CheckBox. Pre nego to
preemo na primer, pogledajmo kontrolu GroupBox, koju smo ranije pomenuli.

Kontrola GroupBox

Pre nego to predemo na primer, pogledaemo kontrolu GroupBox. Ova kontrola se obino koristi
zajedno sa kontrolama RadioButton i CheckBox, da bi napravila okvir i zaglavlje za grupu kontrola
koje su logiki povezane.
Grupni okvir se jednostavno dovue na formular, a zatim se stavljaju ostale kontrole unutar tog
okvira (obrnuto nije mogue - ne moete staviti grupni okvir na ve postojee kontrole). To za
efekat ima da roditelj kontrola postaje grupni okvir, a ne formular, to znai da moe biti
izabrano vise kontrola RadioButton u isto vreme. Meutim, unutar jednog grupnog okvira moe
biti izabrano samo jedno radio dugme.
Odnos roditelj/dete moda zahteva dodatno objanjenje. Kada se kontrola stavi na formular,
kae se da je formular roditelj kontrole, odnosno kontrola je dete formulara. Kada stavite grupni
okvir na formular, grupni okvir postaje dete formulara. Kako grupni okvir sadri nove kontrole, on
postaje roditelj za te kontrole. Ovo znai da kada pomerite grupni okvir, pomeraju se i sve
kontrole koje se nalaze u tom okviru.
Dragi efekat stavljanja kontrola u grupni okvir jeste mogunost menjanja odreenih svojstava
kontrola jednostavnom promenom odgovarajuih svojstava grupnog okvira. Na primer, ako elite
da onesposobite sve kontrole unutar grupnog okvira, moete jednostavno podesiti svojstvo
Enabled grupnog okvira na false.
Prikazaemo primenu grupnog okvira u primeru koji sledi.

Primer kontrole RadioButton i CheckButton

Veba br. 23.


Stari projekat odnosno vebu pod brojem 22. Primer TextBox. Snimite je u drugom folderu,
recimo C:\Temp\SoftIng\LecturesCode\Vezba23.
Otvorite VS .NET i kreirajte novi projekat. Izaberite Visual C# Projects
direktorijum unutar prozora Project Types:, i tip projekta Windows
Application u okviru prozora Templates: U okviru za tekst Location:
promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba23, i
ostavite
podrazumevani
tekst
u
okviru
za
tekst
Name:
KontrolaRadioCheck Button.
Da bi smo iskoristili prethodni primer, prvo ete obrisati iz ve postojeeg
projekta fajl Form1.cs tako to izaberete pomou desnog tastera mia
opciju Delete na selektovan fajl.

Zatim emo dodati fajl sa istim nazivom ali iz prethodnog primera


odnosno vebe 19 koje ste malo pre iskopirali.
Selektujte naziv projekta u prozoru Solution Explorera
KontrolaRadioCheck Button, izaberete pomou desnog tastera mia
opciju Add>Add Existing Item... na selektovan naziv projekta. I birate
naziv fajla Form1.cs iz foldera
C:\Temp\SoftIng\LecturesCode\Vezba23\ Primer TextBox.
I ako ste uradili kako treba, moete otvoriti formu iz prethodnog
primera.

Izmeniemo prethodni primer u kome smo prikazali upotrebu okvira za tekst. U tom primeru
jedino mogue zanimanje je bilo Programer. Umesto da primoramo korisnika da ispisuje ovu re,
promeniemo okvir za tekst u polje za potvrdu.
Da bismo demonstrirali korienje radio dugmeta, traiemo od korisnika jo jednu informaciju:
kojeg je pola.
Izmenite okvir sa tekstom na sledei nain:
1. Uklonite kontrolu lblZanimanje i okvir za tekst TextBox pod nazivom txtZanimanje.

2. Promenite veliinu formulara tako da u njega moe da stane grupni okvir sa informacijom o
polu korisnika, i imenujte nove kontrole kao to je prikazano na slici:

3. Dodajte na formu kontrolu CheckedBox i promenite sledea svojstva:


za CheckBox1
Osobina (Properties)
Name
Text
hecked
Location
Size

Vrednost (Value)
chkProgramer
Programer
True
104; 191
104; 24

4. Dodajte na formu kontrolu GroupBox i promenite sledea svojstva:


za GroupBox1
Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
grpPol
Pol
104; 216
296; 56

5. Dodajte na formu u GroupBox-u dve kontrole RadioButton i promenite sledea svojstva:


za RadioButton1
Osobina (Properties)
Name
Text
hecked
Location
Size

Vrednost (Value)
rdoMusko
Muko
True
24; 24
104; 24

za RadioButton2
Osobina (Properties)
Name
Text
hecked
Location
Size

Vrednost (Value)
rdoZensko
ensko
False
152; 24
104; 24

Primetite da ne mogu obe biti podeene na true. Ako to probate, vrednost osobine drugog radio
dugmeta se automatski menja na false.
Sto se tie izgleda formulara, nikakve dalje intervencije nisu potrebne, ali moramo izmeniti kod.
Prvo moramo izbrisati sve to se odnosi na okvir za tekst koji smo uklonili. Idite na kod i uradite
sledee:
6. U konstruktoru formulara izbriite redove koje se odnose na txtZanimanje. Ovde se misli na
prijavljivanje dogaaja Validacija i TextPromenjen, kao i red koji podeava svojstvo tag
kontrole txtZanimanje na false.
7. U potpunosti uklonite metodu txtZanimanje_Validacija.

Dodavanje rutina za obradu dogaaja


Metod txtBox_TextPromenjen sadrao je test u kome smo proveravali da li je pozivajua
kontrola bila okvir za tekst txtOccupation. Za sada sigurno znamo da nije; zato emo promeniti
metodu brisanjem bloka else if i promenom naredbe if, tako da kod treba da izgleda:

Na jo jednom mestu radimo proveru vrednosti tekstualnog okvira koji smo uklonili - u metodi
ValidateAll (). Potpuno izbriite postojee provere i unesite sledei kod:

Poto koristimo polje za potvrdu, umesto okvira za tekst, znamo da korisnik ne moe uneti
nekorektan podatak, jer e on ili ona uvek biti ili programer, ili nee biti programer.
Takoe, znamo da je korisnik ili muko ili ensko. A poto smo podesili osobinu jednog radio
dugmeta na true, nemogue je da korisnik izabere neispravan podatak. Stoga, jedino to
preostaje da se uradi jeste izmena teksta u kome nalazimo pomo, i izlaznog teksta. Ovo radimo
u rutini za obradu dogaaja dugmeta:

U metodi za dugme OK promene su malo interesantnije:

Prvi od novih redova, koji je naglaen, prikazuje zanimanje korisnika. Proveravamo svojstvo
Checked polja za potvrdu; ako je podeeno na true, prikazujemo niz znakova Programer. A ako je
podeeno na false, prikazujemo Nije programer.
Drugi red proverava samo radio dugme rdoZensko. Ako je svojstvo Checked podeeno na true,
znamo da je korisnik ensko. Ako je podeeno na false, korisnik je muko. Poto postoje samo
dve mogue opcije, nema potrebe da proveravamo drugo radio dugme, jer e svojstvo Checked
tog radio dugmeta uvek biti suprotno podeeno od svojstva Checked prvog radio dugmeta.
Da smo imali vise od dva radio dugmeta, morali bismo proi kroz sve od njih, dok ne pronaemo
ono kod kog je svojstvo Checked podeeno na true.
Kada pokrenete ovaj primer, trebalo bi da dobijete neto slino ovome:
7

Kontrola RichTextBox

Kao i obian okvir za tekst, kontrola RichTextBox (obogaen okvir za tekst) izvedena je iz klase
TextBoxBase. Zbog toga ovi okviri imaju neke slinosti, ali je kontrola RichTextBox mnogo
sadrajnija. Okvir za tekst koristimo za unos kratkih nizova znakova, dok obogaeni tekstualni
okvir koristimo za prikazivanje i unos formatiranog teksta (npr. polucrno, podvueno ili kurziv).
Ovo postiemo korienjem standarda za formatirani tekst koji se zove Rich Text Format
(obogaen tekstualni format) ili RTF.
U prethodnom primeru, koristili smo standardni okvir za tekst. Mogli smo umesto toga koristiti i
obogaeni okvir za tekst. Kao to ete videti u primeru koji sledi, moete ukloniti okvir za tekst
pod nazivom txtOutput, i na njegovo mesto ubaciti obogaeni okvir za tekst sa istim imenom.
Program e se ponaati isto kao i ranije.

Svojstva kontrole RichTextBox

S obzirom na prednosti obogaenog okvira za tekst, on ima i neke nove osobine. Sledea tabela
opisuje neke najee koriene osobine:
Ime osobine

Dostupnost

Opis

CanRedo

Samo itanje

Vrednost ove osobine je true, ako neto to je poniteno moe biti


ponovljeno; u suprotnom je false.

CanUndo

Samo itanje

Vrednost ove osobine je true, ako je mogue izvriti akciju Undo


na obogaeni okvir za tekst; u suprotnom je false.

RedoAc t i onName

Samo itanje

Ovo svojstvo sadri ime akcije koja e biti koriena da bi se


ponovo uradila neka prethodno ponitena radnja u obogaenom
okvira za tekst.

DetectUrls

itanje/upis

Podesite ovu osobinu na true ako elite da kontrola detektuje URL


adrese i da ih formatira (podvue, kao u itau).

Rtf

itanje/upis

Ovo odgovara svojstvu Text, s tim to je tekst u RTF formatu.

SelectedRtf

itanje/upis

Koristite ovu osobinu da biste dobili ili podesili izabrani tekst na


RTF format. Tekst ovako kopiran u drugu aplikaciju, npr. MS Word,
zadrava svoj format.

SelectedText

itanje/upis

Kao i SelectedRtf, moete dobiti ili podesiti izabrani tekst. Za


razliku od prethodne osobine, pri kopiranju tekst ne zadrava svoj
format.

SelectionAlignment

itanje/upis

Ovo svojstvo predstavlja nain poravnavanja izabranog teksta.


Moe biti Center, Left ili Right (centar, levo ili desno).

SelectionBullet

itanje/upis

Uz pomo ove osobine moete saznati da li je neki deo teksta


formatiran sa simbolom za nabrajanje, a moete umetati ili
uklanjati simbol za nabrajanje.

Bulletlndent

itanje/upis

Koristite ovu osobinu da odredite za koliko piksela treba uvui


simbol za nabrajanje.

SelectionColor

itanje/upis

Doputa vam da menjate boju izabranog teksta.

SelectionFont

itanje/upis

Doputa vam da menjate font izabranog teksta.

SelectionLenght

itanje/upis

Uz pomo ove osobine moete podesiti ili saznati duinu izabranog


teksta.

SelectionType

Samo itanje

Ovo svojstvo sadri informacije o izabranom delu. Red e vam da li


je izabran neki OLE objekat ili je izabran samo tekst.

ShowSelectionMargin

itanje/upis

UndoAc t i onName

Samo itanje

SelectionProtected

itanje/upis

Ako podesite ovo svojstvo na true, margina e se pojaviti na levoj


strani kontrole RichTextBox. Ovo omoguava lake biranje teksta.
Uzima ime akcije koja e se koristi u ako korisnik eli da poniti
neku radnju.
Ako podesite ovu osobinu na true, moete odrediti da se odreeni
deo teksta ne menja.

Kao to moete videti, veina novih svojstava se odnosi na biranje. To je zato to se formatiranje
odnosi na onaj deo teksta koji je korisnik izabrao. Ukoliko nikakav izbor nije napravljen,
formatiranje e zapoeti od take u tekstu gde je postavljen kursor, a koja se naziva taka
umetanja.

Dogaaji kontrole RichTextBox

Veina dogaaja koji se koriste u obogaenim okvirima za tekst, isti su kao i za obine okvire za
tekst. Ima i nekoliko novih:
Ime osobine
LinkedClick

Opis
Ovaj dogaaj se alje kada korisnik pritisne vezu unutar teksta.

Protected

Ovaj dogaaj se alje kada korisnik pokua da promeni tekst koji je


oznaen kao zatien.

SelctionChanged

Ovaj dogaaj se alje kada elite neto da izmenite u izabranom


tekstu. Ako iz bilo kojih razloga ne elite da dopustite korisniku da
menja izabrani tekst, moete da ga spreite pomou ovog
dogaaja.

Veba br. 24.


U ovom primeru kreiraemo krajnje jednostavan program za ureivanje teksta, koji pokazuje
kako da izmenite osnovno formatiranja teksta i kako da uitate i snimite tekst iz obogaenog
okvira za tekst. Zbog jednostavnosti, uitavaemo iz fiksirane datoteke i snimaemo u nju.
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Windows Application u okviru prozora Templates: U okviru za tekst Location: promenite
putanju u C:\Temp\SoftIng\LecturesCode\Vezba24 (ovaj e direktorijum biti automatski
napravljen ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
Kontrola RichTextBox.
Otvorite paletu Properties i za kontrolu forme podesite sledee osobine:
Osobina (Properties)
Name
Text
StartPosition
Font
FormBorderStyle
Size

Vrednost (Value)
fclsMain
Kontrola RichTextBox
CenterScreen
Microsoft Sans Serif, Regular, 8, Central
European
FixedSingle
486; 305

Na formu postavite 7 kontroli tipa Button, jednu kontrolu Label, jednu kontrolu TextBox i jednu
kontrolu tipa RichTextBox. Podesite njihova svojstva redom prikazano u tabelama.
Osobina
(Properties)
Name
Text
Cursor
Location
Size

Vrednost (Value) za kontrolu


Button1

Button2

Button3

btnBold
&Bold

btnItalic
&Italic

btnUnderline
&Underline

71; 8

159; 8

247; 8

Button4

Button5

Button6 Button7

btnCentar
&Centar
Hand
335; 8
75; 23

bthLoad
&Load

btnSave
&Save

btnIzlaz
&Izlaz

155; 240

251; 240

400; 240

10

za TextBox1
Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
txtVelicinaFonta
8
244; 40
40; 20

Na formu postavite kontrolu tipa RichTextBox. I postavite svojstva kao u sledeoj tabeli.
Osobina (Properties)
Name
Location
Size

Vrednost (Value)
rtfText
0; 64
480; 168

Podesite svojstva Anchor kontrola kao u tabeli:


Ime kontrole
btnLoad i btnSave
rtfText
Sve ostale

Anchor vrednosti
Buttom
Top, Left, Bottom, Right
Top

Podesite svojstvo MinimumSize formulara da bude isto kao svojstvo Size.

11

Dodavanje rutina za obradu dogaaja

Ovim smo zavrili sa izgledom formulara i prelazimo na kod. Dvaput pritisnite na dugme Bold da
biste dodali ratinu za obradu za Click dogaaj. Ovako izgleda kod:

Poinjemo proverom fonta koji je korien u trenutno izabranom tekstu i dodelimo taj font
lokalnoj promenljivoj. Zatim, proverimo da li je izabrani tekst ve formatiran kao polucrn. Ako
jeste, onda to vise nee biti; u suprotnom elimo da podesimo da bude polucrn. Kreiramo novi
font koristei oldFont kao prototip, a dodajemo ili uklanjamo polucrni stil, zavisno od potrebe.
Na kraju, dodeljujemo novi font izabranom tekstu i vraamo fokus na kontrolu RichTextBox.
Rutine za obradu za btnltalic i btnUnderline su slime kao i prethodne, s tim to proveravamo
odgovarajue stilove. Dva puta pritisnite na dugmad Italic i Underline i dodajte sledei kod:

12

Dvaput pritisnite na poslednje dugme za formiranje, Center, i dodajte sledei kod:

Ovde moramo proveriti jo jednu osobinu, SelectionAlignment, da bismo videli da li je izabrani


tekst ve centriran. HorizontalAlignment moe uzimati vrednosti iz enumeracije, koje mogu biti
Left, Right, Center, Justify ili NotSet. U ovom sluaju jednostavno proverimo da li je podeeno
na Center, i ako jeste, poravnamo tekst po levoj ivici. A ako nije, podesimo tekst na centar.
Poslednje formatiranje koje emo uraditi jeste podeavanje veliine teksta. Dodajemo dve ratine
za obradu dogaaja za tekstualni okvir Size: jedan za kontrolu unosa i drugi koji detektuje da li
je korisnik zavrio unos podatka.
Dodajte sledei kod u konstruktor formulara:

Ove dve rutine za obradu videli smo u prethodnom primeru. Obe koriste pomonu metodu
ApplyTextSize, koja uzima string sa veliinom teksta:

13

Ono to nas zanima deava se u pomonoj metodi ApplyTextSize. Ova metoda poinje
konverzijom stringa (unetog u Size polje) u tip float. Spreili smo korisnika da unosi bilo ta
drugo osim celih brojeva; meutim, kada kreiramo novi font, potreban nam je tip float - zato
radimo ovu konverziju tipova.
Posle toga, koristimo familiju fontova kojoj pripada font, kreiramo novi font u okviru te iste
familije, ali sa novom veliinom. Na kraju, podesimo font izabranog teksta na novokreirani font.
To je sve to moemo da uradimo to se tie formatiranja, iako neke stvari kontrola RichTextBox
sama reava. Ako pokrenete ovaj primer, moete podesiti tekst na polucrn, kurziv ili podvuen, i
moete da centrirate tekst. Ovo je oekivano, ali ima jo neto interesantno. Probajte da
otkucate Web adresu u tekstu, npr. www.tf.zr.ac.yu. Kontrola ovo prepoznaje kao internet
adresu, podvlai je, a kada se pokaziva mia pomeri na adresu, pretvara se u ruku. Ako mislite
da moete da je pritisnete i da vam se otvori odgovarajua Web stranica, skoro da ste u pravu.
Moramo se pozabaviti dogaajem koji se alje kada korisnik pritisne na hipervezu: to je dogaaj
LinkClicked.
14

Ovo emo uraditi prijavom dogaaja u konstruktoru, kao to smo navikli:

Ovu rutinu za obradu dogaaja nismo videli do sada. Koristi se da se doe do teksta veze koja je
pritisnuta. Rutina je iznenaujue jednostavna:

Ovaj kod otvara podrazumevani ita, ako prethodno nije otvoren, i vodi nas na lokaciju na koju
upuuje hiperveza.
Deo aplikacije kojim se ureuje tekst je zavren. Sve to preostaje jeste uitavanje i snimanje
sadraja kontrole. Za to koristimo fiksiranu datoteku.
Dva puta pritisnite na dugme Load i dodajte sledei kod:

Nita vise nije potrebno. Poto radimo sa datotekama, uvek se mogu pojaviti posebni sluajevi,
koje moramo da reimo. U metodi Load moramo reiti poseban sluaj koji se deava ako datoteka
ne postoji. To je jednostavno kao i snimanje datoteka. Dvaput pritisnite na dugme Save i dodajte
sledei kod:

15

Pokrenite ponovo program, formatirajte tekst i pritisnite dugme Save. Izbriite sadraj okvira, a
zatim pritisnite Load i pojavie se tekst koji ste upravo snimili.

Kontrole ListBox i CheckedListBox

Okvir sa listom koristi se za prikaz liste stringova od kojih jedan ili vise moe biti odjednom
izabrano. Kao kod polja za potvrdu i radio dugmeta, okvir sa listom trai od korisnika da izabere
jednu ili vise moguih opcija. Okvir liste trebalo bi da koristite kada, u toku kreiranja aplikacije,
ne znate taan broj opcija koje korisnik moe izabrati (npr. lista zaposlenih). ak i kada unapred
znate broj moguih konkretnih opcija, trebalo bi razmisliti o upotrebi okvira liste ako je taj broj
veliki.
Klasa ListBox je izvedena iz klase ListControl, koja obezbeuje osnovno funkcionisanje dve
kontrole sa listama koje su sastavni deo Visual Studio .NET-a. O drugoj kontroli, ComboBox,
priaemo kasnije u ovom predavanju.
Jo jedna vrsta okvira liste dolazi sa Visual Studio .NET-om: CheckedListBox koja je izvedena iz
klase ListBox. Ova kontrola omoguava potvrdu pojedinanog stringa iz liste.

Svojstva kontrole ListBox

Sve osobine opisane u tabeli koja sledi vae i za ListBox i za CheckedListBox, osim ako nije
drugaije naznaeno:
Ime osobine

Dostupnost

Opis

SelectedIndex

itanje/upis

Vrednost koja pokazuje indeks izabranog elementa u okvira liste


(prvi element u listi ima indeks 0). Ako okvir liste doputa da vise
elemenata bude izabrano odjednom, ovo svojstvo uzima indeks
prvog izabranog elementa.

ColumnWidth

itanje/upis

U okvirima sa vise kolona, ovo svojstvo odreuje irinu kolona.

Items

Samo itanje

Kolekcija Items sadri sve elemente liste. Koristite ovu osobinu za


dodavanje ili izbacivanje elementa.

MultiColumn

itanje/upis

U okvirima sa vise kolona, ovo svojstvo odreuje irinu kolona.

Selectedlndices

Samo itanje

Ovo svojstvo je kolekcija koja sadri indekse izabranih elemenata,


pri emu indeksiranje poinje od nule.

Selectedltem

itanje/upis

Selectedltems

Samo itanje

SelectionMode

itanje/upis

Sorted

itanje/upis

U listi koja doputa biranje samo jednog elementa, ovo svojstvo


sadri taj element. Ako se u listi moe izabrati vise elemenata,
svojstvo sadri prvi izabrani element.
Ovo svojstvo je kolekcija koja sadri sve trenutno izabrane
elemente.
Postoje

etiri naina biranja elemenata u listi:


None: nijedan element ne moe biti izabran.
One: samo jedan element moe biti izabran.
MultiSimple: vise elemenata moe biti izabrano.
MultiExtended: vise elemenata moe biti izabrano i moe
se koristiti Ctrl, Shift i tasteri sa strelicama za biranje.

Ako podesite ovu osobinu na true, kontrola ListBoxce sortirati


elemente po abecednom redu.

16

Ime osobine

Dostupnost

Opis

Text

itanje/upis

Ovo svojstvo se razlikuje od Text svojstava ostalih kontrola. Ako


podesite Text osobinu okvira liste, ona e tragati za elementom
koji ima to ime i izabrae ga. Ako, sa druge strane, itate vrednost
Text osobine, vraena vrednost je prvi izabrani element. Ovo
svojstvo ne moe biti korieno ako je svojstvo SelectionMode
podeeno na None.

Checkedlndicies

Samo itanje

Samo za kontrolu CheckedListBox: ovo svojstvo sadri sve indekse


elemenata koji su potvreni ili koji imaju neodreen status.

CheckedItems

Samo itanje

Samo za kontrolu CheckedLi s tBox: ovo je kolekcija koja sadri


sve elemente koji su potvreni ili koji imaju neodreen status.

CheckOnClick

itanje/upis

Samo za kontrolu CheckedListBox: ako je ovo svojstvo podeeno na


true, element menja stanje kad god korisnik pritisne na njega.

ThreeDCheckBoxes

itanje/upis

Samo za kontrolu CheckedListBox: podeavanjem ove osobine


moete birati da li e polja za potvrdu biti ravna ili normalna.

Metode kontrole ListBox

Zbog efikasnog rada sa okvirima liste, morate znati neke metode koje okvir moe pozvati. Tabela
koja sledi opisuje samo najee koriene metode. Metode vae i za kontrolu ListBox i za
CheckedListBox, osim ako nije drugaije naznaeno:
Ime
ClearSelected
FindString
FindstringExact

Opis
Ponitava izbor u okviru liste.
Pronalazi prvi string u listi koji poinje eljenim stringom, npr.
FindString ("a ") e nai prvi string u listi koji poinje sa 'a'.
Kao i FindString, s dm to se kompletan string mora podudarati.

GetSelected

Vraa vrednost koja pokazuje da li je element izabran ili nije.

SetSelected

Podeava da element bude izabran, ili brie element iz liste


izabranih elemenata.

ToString
GetltemChecked
GetltemCheckState
SetltemChecked

SetltemCheckState

Vraa trenutno izabrani element.


Samo za kontrolu CheckedLi stBox: vraa vrednost koja pokazuje
da li je element potvren ili ne.
Samo za kontrolu CheckedListBox: vraa vrednost koja
pokazuje stanje elementa.
Samo za kontrolu CheckedListBox: podeava odreeni element
tako da bude potvren
Samo za kontrolu CheckedListBox: podeava stanje elementa.

17

Dogaaji kontrole ListBox

Obino, dogaaji kojih elite da budete svesni dok radite sa kontrolama ListBox
CheckedListBox, jesu oni dogaaji koji se odnose na izbor korisnika:
Ime

Opis

ItemCheck

Samo za kontrolu CheckedListBox: deava se kada se menja


stanje elementa.

SelectedlndexChanged

Deava se kada se menja indeks izabranog elementa.

Primer kontrole ListBox

Veba br. 25.


Napraviemo manji primer koji ukljuuje kontrole ListBox i CheckedListBox. Korisnik moe
potvrditi element u kontroli CheckedListBox, zatim pritisnuti na dugme koje e pomeriti
potvrene elemente u kontrolu ListBox. Kreiramo dijalog na sledei nain:
Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types: i tip projekta
Windows Application u okviru prozora Templates: U okviru za tekst Location: promenite
putanju u C:\Temp\SoftIng\LecturesCode\Vezba25 (ovaj e direktorijum biti automatski
napravljen ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
Kontrola ListBox.
Dodajte kontrole ListBox, CheckedListBox i Button, i imenujte ih kao to je prikazano na slici:

Otvorite paletu Properties i za kontrolu forme podesite sledee osobine:


Osobina (Properties)
Name
Text
StartPosition
Font
FormBorderStyle
Size

Vrednost (Value)
fclsMain
Kontrola ListBox
CenterScreen
Microsoft Sans Serif, Regular, 8, Central
European
FixedSingle
382; 237
18

za Button1
Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
btnPrebaci
Prebaci
152; 80
75; 23

za ChekedListBox1
Osobina (Properties)
Name
CheckOnClick

Items

Location
Size

Vrednost (Value)
chkListaIzbora
True
jedan
dva
tri
etiri
pet
est
sedam
osam
devet
8; 8
136; 184

za ListBox1
Osobina (Properties)
Name
Location
Size

Vrednost (Value)
lstSelektovani
232; 8
136; 186

Dodavanje rutina za obradu dogaaja

Sada smo spremni za dodavanje koda. Kada korisnik pritisne dugme Move, elimo da pronademo
elemente koji su potvreni i da ih kopiramo u okvir sa listom Selected.
Dva puta pritisnite dugme i dodajte sledei kod:

19

Poinjemo tako to proveravamo svojstvo Count kolekcije CheckedItems. Vrednost osobine


Count bie vea od nule ako je neki element liste potvren. Zatim, uklanjamo sve elemente iz
okvira Selected, prolazimo kroz kolekciju CheckedItems dodajui svaki element te kolekcije u
okvir Selected. Na kraju, podeavamo sve elemente u okvira CheckedListBox tako da ne budu
potvreni.
Sada nam jo trebaju elementi koje emo pomerati. Mogli bismo dodati ove elemente u reimu
dizajna, biranjem svojstva Item i upisivanjem stavki. Umesto toga, dodaemo elemente direktno
iz koda. To postiemo u konstruktoru formulara:

Kao to biste unosili vrednosti u panelu Properties, moete koristiti kolekciju Items u vreme
izvravanja.
Ovim zavravamo primer za okvire liste. Ako pokrenete ovaj program, dobiete neto nalik
ovome:

20

Korienje kontrola za
Windows formulare III deo
Kontrola ComboBox

to ime implicira, kontrola ComboBox (kombinovani okvir) sadri nekoliko kontrola, tanije:
kontrole TextBox, Button i ListBox. Za razliku od kontrole Listbox, u kontroli ComboBox nije
mogue izabrati vise od jednog elementa liste, ali je mogue uneti nove elemente otkucavanjem
njihovih imena u polju TextBox kombinovanog okvira.
Uobiajeno je da se kontrola ComboBox koristi kada elimo da utedimo prostor u dijalogu, zbog
toga to su stalno vidljivi delovi kombinovanog okvira samo tekstualni okvir i kontrole Button.
Kada korisnik pritisne na dugme sa strelicom desno od tekstualnog okvira, pojavljuje se okvir
liste u kojem korisnik moe izabrati odreeni element. im korisnik izabere neki element, okvir
liste nestaje, a izabrani element se pojavljuje u tekstualnom okvira, vraajui normalan izgled
dijalogu. Pogledaemo osobine i dogaaje kontrole ComboBox i napraviti primer koji ukljuuje
ComboBox i dve kontrole ListBox.

Svojstva kontrole ComboBox

Kako kontrola ComboBox poseduje mogunosti kontrola TextBox i ListBox, mnoge osobine
kombinovanog okvira mogu se nai i u dve pomenute kontrole; zbog ovoga, postoji ogroman broj
svojstava i dogaaja kontrole ComboBox, ali mi demo opisati samo najee koriene.
Kompletnu listu pogledajte u MSDN biblioteci.
Ime osobine

Dostupnost

Opis

DropDownStyle

itanje/upis

Kombinovani okvir moe biti prikazan u tri razliita stila:

DropDown: korisnik moe upisivati u tekstualni okvir, ali mora


pritisnuti na dugme sa strelicom za prikaz kompletne liste
elemenata.

Simple: isto kao i DropDown s dm to je lista uvek vidljiva,


slino obinoj kontroli ListBox.

DropDownList: korisnik ne moe upisivati novi element u


tekstualni okvir i mora pritisnuti na dugme sa strelicom za
prikaz liste elemenata.

DroppedDown

itanje/upis

Pokazuje da li je lista prikazana ili nije. Ako podesite ovu osobinu na


true, lista e se prikazati.

Items

Samo itanje

Kolekcija koja sadri sve elemente liste iz kombinovanog okvira.

MaxLength

itanje/upis

Podeavanjem ove osobine na broj vei od nule, odreujete maksimalan


broj karaktera koji je mogue uneti u tekstualni deo kontrole.

Selectedlndex
Selectedltem

itanje/upis

Pokazuje indeks trenutno izabranog elementa liste.

itanje/upis

Pokazuje trenutno izabrani element liste.

SelectedText

itanje/upis

Predstavlja tekst koji je izabran u tekstualnom delu kontrole.

SelectionStart

itanje/upis

Predstavlja indeks prvog karaktera dela teksta koji je izabran u


tekstualnom delu kontrole.

SelectionLength

itanje/upis

Predstavlja duinu izabranog teksta u tekstualnom delu kontrole.

Sorted

itanje/upis

Ako podesite ovu osobinu na true, kontrola e sortirati elemente liste


po abecednom redu.

itanje/upis

Ako podesite ovu osobinu na vrednost null, nita nee biti izabrano u
lisa. Ako podesite na vrednost koja postoji u listi, ta vrednost e biti
izabrana. Ako traena vrednost ne postoji u listi, tekst e biti prikazan u
tekstualnom delu kontrole

Text

Dogaaji kontrole ComboBox

Postoje tri osnovne akcije za koje elite da znate kada se dese u kombinovanom okviru:
Kada se promeni izbor;
Kada se menja stanje liste (da li je prikazana ili nije);
Kada se tekst menja.
Da biste obradili ove tri akcije, obino se morate prijaviti za jedan ili vie od sledeih dogaaja:
Ime
DropDown

Opis
Deava se kada se prikae deo sa okvirom sa listom.

SelectedlndexChanged

Deava se kada se umesto jednog elementa u listi izabere neki


drugi element.

KeyDown
KeyPress
KeyUp

Ovi dogaaji deavaju se kada se pritisne taster dok tekstualni


deo kontrole ima fokus. Pogledajte objanjenja ovih dogaaja
za tekstualni okvir.

TextChanged

Deava se kada se menja svojstvo Text.

Primer kontrole ComboBox

Veba br. 26.


Ponovo emo koristiti primer za tekstualne okvire. Setite se da smo u primeru za kontrolu
CheckBox promenili okvir za tekst Zanimanje u polje za potvrdu. Trebalo bi da postoji neko
drago zanimanje osim programera, zato emo napraviti jo jednu izmenu. Za ovu promenu
koristiemo kombinovani okvir koji e sadrati dva mogua zanimanja: konsultant i programer.
Takoe, dopustiemo korisniku da unese i ostala zanimanja, ukoliko korisnik nije ni konsultant ni
programer. Da korisnik ne bi morao iznova unositi svoje zanimanje svaki put kada koristi
aplikaciju, snimiemo uneti element u datoteku kad god se dijalog zatvara. Takoe, uitaemo
sve elemente iz datoteke kad god se dijalog otvara.
Stari projekat odnosno vebu pod brojem 22. PrimerTextBox. Snimite je u drugom folderu,
recimo C:\Temp\SoftIng\LecturesCode\Vezba26.
Otvorite VS .NET i kreirajte novi projekat. Izaberite Visual C# Projects
direktorijum unutar prozora Project Types:, i tip projekta Windows
Application u okviru prozora Templates: U okviru za tekst Location:
promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba26, i
ostavite podrazumevani tekst u okviru za tekst Name: Kontrola
ComboBox.
Da bi smo iskoristili prethodni primer, prvo ete obrisati iz ve postojeeg
projekta fajl Form1.cs tako to izaberete pomou desnog tastera mia
opciju Delete na selektovan fajl.

Zatim emo dodati fajl sa istim nazivom ali iz prethodnog primera


odnosno vebe 19 koje ste malo pre iskopirali.
Selektujte naziv projekta u prozoru Solution Explorera
KontrolaRadioCheck Button, izaberete pomou desnog tastera mia
opciju Add>Add Existing Item... na selektovan naziv projekta. I birate
naziv fajla Form1.cs iz foldera
C:\Temp\SoftIng\LecturesCode\Vezba26\ Kontrola ComboBox.
I ako ste uradili kako treba, moete otvoriti formu iz prethodnog
primera.
Ponimo sa promenom izgleda dijaloga:
Uklonite polje za potvrdu chkProgrammer.
Dodajte oznaku i kombinovani okvir sa imenima, kao to je prikazano na slici:

Podesite svojstva kontrola:


za Label
Osobina (Properties)
Name
Text
TextAlign
Location
Size

Vrednost (Value)
lblZanimanje
Zanimanje:
TopRight
26; 195
72; 23

za ComboBox1
Osobina (Properties)
Name
Location
Size

Vrednost (Value)
cboZanimanje
104; 191
296; 21

Text oznake na Zanimanje i izbriite svojstvo Text kontrole Combo-Box.


Nisu potrebne dalje promene formulara.
Kreirajte u radnom folderu jo tekstualnu datoteku Zanimanje.txt koja sadri sledea dva reda:
Konsultant
Programer

Dodavanje rutina za obradu dogaaja

Sada moemo menjati kod. Pre nego to ponemo sa pisanjem novog koda, promeniemo kod
ratine za obradu dogaaja btnOK_Click da bi se podudarao sa promenama formulara:

Umesto polja za potvrdu, sada koristimo kombinovani okvir. Kada je element liste izabran,
pojavie se u tekstualnom delu kontrole ComboBox; zbog ovoga, vrednosti koje nas interesuju
uvek e se nalaziti u svojstvu Text kombinovanog okvira.

Sada moemo zapoeti pisanje novog koda. Pre svega, kreiraemo metodu koja uitava vrednosti
koje ve postoje u tekstualnoj datoteci (Zanimanje.txt) i ubaciemo te vrednosti u kombinovani
okvir:

itanje podataka iz ulaznih tokova (pomou objekta StreamReader) se neemo ovde baviti, sami
pronaite u MSD bibloteci. Dovoljno je red da pomou ovog objekta otvaramo tekstualnu
datoteku Zanimanje.txt i itamo elemente za kombinovani okvir, red po red. Dodajemo svaki red
datoteke kombinovanom okviru tako to primenjujemo metodu Add() na kolekciju Items.
Poto korisnik moe uneti novi element u kombinovani okvir, proveravamo sluaj kada je
pritisnut taster Enter. Ako tekst iz svojstva Text kombinovanog okvira ne postoji u kolekciji
Items, dodajemo novi element toj kolekciji:

Metoda FindStringExact () objekta ComboBox trai onaj string koji se u potpunosti podudara sa
unetim stringom, ne vodei rauna o malim i velikim slovima. Ovo je savreno za nas, jer ne
elimo da dodamo varijante istog zanimanja u kolekciju.
Ako ne naemo element u kolekciji Items koji se podudara sa unetim tekstom, dodajemo novi
string u kolekciju. Dodavanje novog stringa automatski podeava trenutno izabrani element na
onaj koji je upravo unet. Ukoliko pronaemo podudarnost, jednostavno biramo postojei element
kolekcije.
Takoe, potrebno je da se prijavimo na dogaaj u konstruktoru formulara:

Kada korisnik zatvori dijalog, trebalo bi snimiti elemente kombinovanog okvira. To postiemo
sledeom metodom:

Klasa StreamWriter takoe pogledajte u helpu. Kod za upis teksta u datoteku stavljamo u blok
try.. .catch, u sluaju da korisnik izbrie ili pomeri tekstualnu datoteku dok je formular jo uvek
otvoren.
Prolazimo kroz kolekciju Items i upisujemo svaki element u datoteku Zanimanje.txt.
Konano, moramo pozvati metode LoadOccupation() i SaveOccupation() koje smo upravo
kreirali. To radimo u konstruktoru formulara i metodi Dispose(), tim redom:

Ovim zavravamo ComboBox primer. Kada pokrenete program, trebalo bi da dobijete neto nalik
ovome:

Kontrola ListView

Lista iz koje moete birati datoteke, koje elite otvoriti u standardnom Windows dijalogu, zove
se kontrola ListView. Sve to moete uraditi vezano za prikaz u standardnom dijalogu (velike
ikone, detaljni prikaz itd.) moete uraditi i u kontrolama ListView koje su sastavni deo Visual
Studio .NET-a:
Kontrola ListView se obino koristi za prikaz podataka gde korisnik moe menjati sol prikazivanja.
Podatke koje kontrola sadri mogue je prikazati razliitim ikonama u kolonama i redovima, ili u
jednoj koloni. Najee koriena kontrola ListView jeste ona koju vidimo na slici iznad, za
navigaciju kroz direktorijume.
Kontrola ListView je najkompleksnija kontrola sa kojom se sreemo u ovom predavanju. Opisati
sve njene komponente bilo bi isuvie za ovu knjigu. Meutim, kroz primer ete videti osnovne
informacije o veini najznaajnijih mogunosti kontrole ListView, kao i detaljne opise svojstava,
dogaaja i metoda. Takoe, pogledaemo i kontrolu ImageList koja uva slike koriene u
kontroli ListView.

Svojstva kontrole ListView


Ime osobine

Dostupnost

Opis

itanje/upis

Korienjem ove osobine moete kontrolisati kako korisnik aktivira


elemente iz kontrole ListView. Ne bi trebalo menjati podrazumevanu
vrednost osobine, ukoliko nemate dobar razlog za promenu, zato to se
promena podeene vrednosti odnosi na ceo sistem. Mogue vrednosti su:

Standard: ona vrednost koju je korisnik ve izabrao za ceo


sistem.

OneClick: jedan pritisak miem aktivira element.

TwoClick: dvostruki pritisak miem aktivira element.

itanje/upis

Ovom osobinom reguliete poravnanje elementa u kontroli ListView.


etiri mogue vrednosti su:

Default: element ostaje tamo gde ga je korisnik prevukao i


spustio.

Left: elementi su poravnati po levoj ivici kontrole ListView.

Top: elementi su poravnati po gornjoj ivici kontrole ListView.

SnapToGrid: ListView kontrola ima nevidljivu mreu po kojoj su


elementi poravnati.

itanje/upis

Ako podesite ovu osobinu na true, dozvoljavate korisniku da menja


redosled kolona. Ako to uradite, morate imati rutine koje e valjano
ubacivati elemente u listu, bez obzira na to da li je redosled kolona
promenjen ili nije.

AutoArrange

itanje/upis

Ako podesite ovu osobinu na true, element e zauzeti poloaj prema


vrednosti svojstva Alignment. Ako je, na primer, svojstvo Alignment
podeeno na Left, kada korisnik prevue element do centra kontrole,
onda se element automatski pomera na levu ivicu kontrole. Podeavanje
ove osobine ima efekta samo ako je svojstvo View podeeno na
Largelcon ili Smalllcon.

CheckBoxes

itanje/upis

Ako podesite ovu osobinu na true, svaki element u listi imae polje za
potvrdu levo od sebe. Podeavanje ove osobine ima efekta samo ako je
svojstvo View podeeno na Details ili List.

Checkedlndices
Checkedlterns

Samo itanje

Ova dva svojstva daju pristup kolekcijama koje sadre indekse i


elements koji su potvreni.

Columns

Samo itanje

Kontrola ListView moe imati kolone. Ovo svojstvo obezbeuje pristup


kolekciji kolona, kroz koju moete dodavati ili uklanjati kolone.

Focusedltem

Samo itanje

Ovo svojstvo sadri element koji ima fokus. Ako nita nije izabrano,
vrednost je null.

Activation

Alignment

AllowColumn
Reorder

Ime osobine

Dostupnost

Opis

FullRowSelect

itanje/upis

Ako je ovo svojstvo podeeno na true, kada se pritisne na neki element,


onda e ceo red u kom se element nalazi biti naglaen. Ako je podeeno
na false, samo e element biti naglaen.

GridLines

itanje/upis

Podeavanjem ove osobine na true pokazae se linije mree izmeu


redova i kolona. Podeavanje ove osobine ima efekta samo ako je
svojstvo view podeeno na Details.

HeaderStyle

itanje/upis

Moete
stila:

HoverSelection

itanje/upis

Kada je ovo svojstvo podeeno na true, korisnik moe izabrati element


postavljanjem mia na element.

Items

Samo itanje

LabelEdit

itanje/upis

LabelWrap

itanje/upis

LargelmageList

itanje/upis

MultiSelect

itanje/upis

Scrollable

itanje/upis

Selectedlndices

Samo itanje

Sadri indekse izabranih elemenata.

Selectedltems

Samo itanje

Sadri izabrane elemente.

SmallImageList

itanje/upis

Ovo svojstvo sadri kontrolu ImageList u kojoj se nalaze slike. Ove slike
se mogu koristiti kada je svojstvo View podeeno na Smalllcon.

Sorting

itanje/upis

Kontrola ListView moe sortirati elemente koje sadri. Postoje tri


razliita naina:

Ascending: po rastuem redosledu.

Descending: po opadajuem redosledu.

None: nema sortiranja.

StatelmageList

itanje/upis

Kontrola ImageList sadri maske za slike koje se koriste za prekrivanje


slika iz kolekcija LargelmageList i SmalllmageList, u cilju prikazivanja
trenutnog stanja.

Topitern

Samo itanje

Vraa element koji se nalazi na vrhu liste.

itanje/upis

Kontrola moe pokazati elemente u etiri razliita reima:

Largelcon: svi elementi su prikazani kao velike ikone (32 x 32)


sa oznakama.

Smalllcon: svi elementi su prikazani kao male ikone (16 x 16) sa


oznakama.

List: prikazana je samo jedna kolona koja moe da sadri ikonu


i oznaku.

Details: bilo koji broj kolona moe biti prikazan. Samo prva
kolona moe da sadri ikonu.

View

kontrolisati kako e biti prikazano zaglavlje kolone. Postoje tri


Clickable: zaglavlje kolone se ponaa kao dugme.
NonClickable: zaglavlje kolone ne reaguje na pritisak miem.
None: zaglavlja kolona nisu prikazana.

Kolekcija elemenata u lisa.


Kada je vrednost ovog svojstva podeena na true, korisnik moe
ureivati sadraj prve kolone u prikazu Details.
Kada je ovo svojstvo podeeno na true, oznake e se protezati na koliko
god je redova potrebno za prikazivanje celog teksta.
Ovo svojstvo sadri kontrolu ImageList u kojoj se nalaze velike slike.
Ove slike se mogu koristiti kada je svojstvo View podeeno na
Largelcon.
Podesite ovu osobinu na true, ako hoete da dozvolite korisniku da
izabere vise elemenata odjednom.
Ako podesite ovu osobinu na true, pokazae se traka za pomeranje
sadraja.

Metode klase ListView

Za kompleksnu kontrolu kakva je ListView, postoji iznenaujue mali broj metoda. Sve su
opisane u sledeoj tabeli:
Ime

Opis

BeginUpdate

Pozivanjem ove metode stopirate osveavanje (auriranje)


slike, sve dok se ne pozove metoda EndUpdate. Ovo moe biti
korisno, pogotovu ako ubacujete veliki broj elemenata
odjednom; spreava se treptanje prikaza i znaajno se
poveava brzina.

Clear

Kompletno uklanja sve elemente i kolone kontrole ListView.

EndUpdate

Ovu metodu pozivate posle metode BeginUpdate. Kada je


pozovete, svi elementi e biti iscrtani u kontroli ListView.

EnsureVisible

Kada pozovete ovu metodu, lista e se pomeriti do onog


elementa iji je indeks prosleen metodi.

GetltemAt

Vraa element u listi koji se nalazi na poziciji x, y.

Dogaaji kontrole ListView

Sledea tabela opisuje dogaaje koje moete pozivati za kontrolu ListView:


Ime
AfterLabelEdit
BeforeLabelEdit

Opis
Ovaj dogaaj nastaje posle ureivanja oznake.
Ovaj dogaaj nastaje pre nego to korisnik zapone ureivanje
oznake.

ColumnClick

Ovaj dogaaj nastaje kada je kolona pritisnuta.

ItemActivate

Deava se kada se element aktivira.

Klasa ListViewltem

Element liste je uvek objekat klase Listviewltem. Klasa ListViewltem sadri informacije, kao to
su tekst i indeks ikone, koje treba prikazati. Takoe, sadri kolekciju koja se zove SubItems. Ova
kolekcija sadri objekte klase ListViewSubItems. Ovi podelementi su prikazani ako je kontrola
ListView u reimu Details. Svaki od podelemenata predstavlja kolonu. Osnovna razlika izmeu
elementa i podelementa jeste ta to podelement ne moe prikazati ikonu. Objekte ListViewltem
dodajete kontroli ListView kroz kolekciju Items. Objekte ListViewSubItems dodajete kontroli
ListViewltem kroz kolekciju SubItems.

Klasa ColumnHeader

Za prikazivanje zaglavlja kolona, dodajete objekte klase ColumnHeader kontroli List-View, kroz
kolekciju Columns. Klasa ColumnHeader obezbeuje zaglavlje za kolone koje e se prikazati kada
je ListView u reimu Details.

Kontrola ImageList

Kontrola ImageList obezbeuje kolekciju koja se koristi za smetanje slika koje mogu biti
koriene u drugim kontrolama. U liste slika mogu se stavljati slike bilo koje veliine, s tim da se
u okviru jedne kontrole mogu nai samo slike iste veliine. U sluaju kontrole ListView potrebne
su dve kontrole ImageList za smetanje malih i velikih slika. ImageList je prva kontrola s kojom se
sreemo u ovom predavanju koja ne prikazuje svoj sadraj u vremenu izvravanja programa.
Kada dovuete ovu kontrolu na formular za vreme dizajniranja, ona ne postaje deo samog
formulara ve se nalazi u bloku ispod formulara, koji smeta sve sline objekte. Ovo zanimljivo
svojstvo ne doputa kontrolama koje nisu deo grafikog interfejsa da zatrpavaju dizajner
formulara. Kontrolom ImageList se rukuje kao i svakom drugom kontrolom, s tim da je ne moete
10

pomerati.
Slike se mogu dodavati kontroli ImageList i u vreme dizajniranja i u vreme izvravanja programa.
Ako unapred znate koje slike elite prikazati, moete pritisnuti na dugme desno od svojstva
Images. Prikazae se dijalog u kojem moete doi do eljenih slika. Ako se odluite za dodavanje
slika u toku izvravanja programa, to moete postii kroz kolekciju Images.
Primer kontrole ListView
Napraviemo dijalog sa kontrolom ListView i dve kontrole ImageList. ListView e prikazati
datoteke i direktorijume smetene na vaem disku. Zbog jednostavnosti, neemo izvlaiti tane
ikone datoteka i direktorijuma, ve emo koristiti standardne ikone za direktorijume i datoteke.
Otvaranje direktorijuma omoguie vam da pretraujete stablo direktorijuma, a dugme Back da
se vratite unazad. etiri radio dugmeta koristiemo za promenu prikaza liste u toku izvravanja
programa. Ako se dva puta pritisne neka datoteka, pokuaemo da je otvorimo (izvrimo) i uvek,
poinjemo kreiranjem grafikog interfejsa:

Veba br. 27.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Windows Application u okviru prozora Templates: U okviru za tekst Location: promenite
putanju u C:\Temp\SoftIng\LecturesCode\Vezba27 (ovaj e direktorijum biti automatski
napravljen ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
Kontrola ListView.
Otvorite paletu Properties i za kontrolu forme podesite sledee osobine:
Osobina (Properties)
Name
Text
StartPosition
FormBorderStyle
Size

Vrednost (Value)
fclsMain
Kontrola ListView
CenterScreen
FixedSingle
558; 325

Dodajte kontrolu Labele, i podesite sledee osobine:


Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
lblTrenutnaPutanja
16; 8
528; 16

Dodajte kontrolu dugmeta, i za kontrolu Button podesite sledee osobine:


Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
btnNazad
Nazad
240; 256
75; 23

Dodajte jednu kontrolu grupnog okvira ili GroupBox i u nju etiri kontrole radio dugmeta Radio
Button grupnom okviru i podesite njihove osobine u prozoru Properties, redom.
11

za GroupBox1
Osobina (Properties)

Vrednost (Value)

Name
Text
Location
Size

groPregledMod
Pregled mod
424; 32
120; 128

za etiri kontrole RadioGroup


Osobina
(Properties)
Name
Text
Checked
Location
Size

Vrednost (Value) za kontrolu


RadioGroup1 RadioGroup2 RadioGroup3 RadioGroup4
rdoLargeIcon
Velike Ikone
false
8; 24
96; 16

rdoSmallIcon
Male Ikone
false
8; 48
104; 16

rdoList
List Pregled
true
8; 72
104; 16

rdoDetails
Detalj Pregled
false
8; 96
104; 16

Dodajte dve nevidljive kontrole ImageList na formu tako to ete dva puta pritisnuti ikonu
kontrole u okviru sa alatima (moraete da ga pomerite nadole da biste pronali ikonu). Promenite
svojstva u prozoru Properties za ImageList kontrole: Vrednost (Value) za kontrolu
Osobina
(Properties)
Name
ImageSize

ImageList1

ImageList2

ilMaleIkone
16; 16

ilVelikeIkone
32; 32

<Oznaka diska>:\Visual Studio Files\Graphics\Icons\Win95\16X16


Images

Folder.ico
<Oznaka diska>:\Visual Studio Files\Graphics\Icons\Win95\16X16
Files.ico

Dodajte kontrolu ListView, i za kontrolu ListView podesite sledee osobine:


Osobina (Properties)
Name
View
LargeImageList
SmallImageList
MultiSelect
Location
Size

Vrednost (Value)
lwFajloviFolderi
List
ilVelikeIkone
ilMaleIkone
true
16; 32
558; 325

Dobijate formular kao na slici:

12

Dodavanje rutina za obradu dogaaja

Ovim zavravamo sa grafikim interfejsom i prelazimo na kod. Pre svega, treba nam polje u koje
e se smetati direktorijumi kroz koje smo ve proli, tako da se moemo vratiti na njih kada se
pritisne dugme Nazad. uvaemo apsolutne putanje do direktorijuma, i za taj posao koristimo
StringCollection:

Nismo napravili zaglavlje kolone; zato emo to sada uraditi. Pravimo ih u metodi
KreirajHeaderListView():

Poinjemo deklarisanjem promenljive colHead, koja se koristi za kreiranje tri zaglavlja. Za svako
od ova tom zaglavlja kreiramo novu promenljivu, i dodeljujemo joj svojstvo Text pre nego to je
dodamo u kolekciju Columns kontrole ListView.
13

Ostaje jo inicijalizacija formulara sadrajem koji se prikazuje na poetku, a to je popunjavanje


kontrole ListView datotekama i direktorijumima sa diska. Ovo radimo u sledeem metodu:

14

Pre prvog od dva bloka foreach, pozivamo metod BeginUpdate() za kontrolu ListView. Setite se
da metoda BeginUpdate() stopira osveavanje (auriranje) slike sve dok se ne pozove metoda
EndUpdate(). Da nismo dodali ovu metodu, ispunjavanje liste bi bilo znatno sporije i slika bi
treptala kako se elementi dodaju. Neposredno posle drugog bloka foreach pozivamo metodu
EndUpdate(), koja prikazuje sve elemente kontrole ListView.
Posebno nas interesuju dva bloka foreach. Poinjemo tako to kreiramo novi objekat klase
ListViewItem i podeavamo svojstvo Text na ime datoteke ili direktorijuma koji emo ubaciti.
Svojstvo Imagelndex objekta ListViewItem odnosi se na indeks elementa u jednoj od kontrola
ImageList. Zbog ovoga, vano je da ikone imaju iste indekse u obe kontrole ImageList. Koristimo
svojstvo Tag za smetanje putanje do datoteka i direktorijuma, koju koristimo kada korisnik dva
puta pritisne element.
Zatim, kreiramo dva podelementa. Njima je dodeljen tekst za prikazivanje, posle ega dodajemo
podelemente kolekciji Subltems objekta ListViewItem.
Konano, objekat ListViewItem dodat je kolekciji Items kontrole ListView. Kontrola ListView je
dovoljno pametna da ignorie podelemente ukoliko reim prikaza liste nije Details. Zato,
dodajemo podelemente bez obzira na trenutni reim.
Ostaje jedino da prikaemo koreni direktorijum pozivanjem dve funkcije u konstruktoru
tormulara. U isto vreme stvaramo instancu klase StringCollection pod imenom folderCol i
inicijalizujemo je korenim direktorijumom:

15

Da bi korisnik bio u stanju da,dva puta pritisne element u kontroli ListView i tako pretrauje
direktorijume, moramo da prijavimo dogaaj ItemActivate. To radimo u konstruktoru:

Odgovarajua ratina za obradu ovog dogaaja izgleda ovako:

Svojstvo tag izabranog elementa sadri punu putanju do datoteka i direktorijuma na koje se dva
puta pritisne. Znamo da su slike sa indeksom 0 direktorijumi; prema tome, moemo utvrditi da li
je element datoteka ili direktorijum ako pogledamo u njegov indeks. Ako je datoteka,
pokuaemo da ga otvorimo. Ako je direktorijum, pozivamo metodu PaintListView sa putanjom
novog direktorijuma. Zatim, dodajemo novi direktorijum kolekciji folderCol.

16

Pre nego to predemo na radio dugmad, zavriemo mogunosti pretraivanja dodajui rutinu za
obradu pritiska dugmeta Back. Dva puta pritisnite dugme Back i dodajte sledei kod:

Ako postoji vise od jednog elementa u kolekciji folderCol, znad da nismo u korenom
direktorijumu, pa pozivamo metod PaintListView sa putanjom do prethodnog direktorijuma.
Poslednji element u kolekciji folderCol jeste direktorijum u kom se trenutno nalazimo; zbog toga
treba uzeti pretposlednji direktorijum. Zatim, uklanjamo poslednji element kolekcije i
pomeramo se na pretposlednji. Ukoliko postoji samo jedan element u kolekciji, jednostavno
pozivamo metodu PainListView sa tim elementom.
Ostaje dodavanje koda za etiri radio dugmeta, da bismo mogli menjati tip prikaza liste. Dva
puta pritisnite svako radio dugme i dodajte sledei kod:

Proveravamo svojstvo Checked za svako radio dugme. Ako je svojstvo podeeno na true,
podeavamo svojstvo View kontrole ListView shodno tome.

17

Ovim zavravamo ListView primer. Kada pokrenete program, trebalo bi da dobijete neto nalik
ovome:

Kontrola StatusBar

Statusna linija se najee koristi za prikazivanje uputstva za izabrani element ili za informaciju
o akciji koja se trenutno izvodi. Uobiajeno, kontrola StatusBar se postavlja u dnu ekrana, kao
to je to sluaj sa MS Office aplikacijama, ali moe se staviti i na neko drugo mesto. Visual
Studio.NET statusna linija se koristi za prikazivanje teksta. Takoe, moete dodavati panele za
prikaz teksta, kao i sopstvene ratine za iscrtavanje sadraja panela:

Slika iznad prikazuje statusnu liniju MS Worda. Paneli statusne linije, tj. sekcije, prikazuju se kao
ulegnute.

Svojstva kontrole StatusBar

Kao to smo ve rekli, moete podesiti svojstvo Text statusne linije za prikazivanje nekog teksta,
ali, takoe je mogue praviti panele u iste svrhe:

Ime osobine

Dostupnost

Opis

Backgroundlmage

itanje/upis

Mogue je dodeliti sliku statusnoj liniji, koja e se iscrtati u pozadini.

Panels

itanje/upis

Ovo je kolekcija panela u statusnoj liniji. Koristite ovu kolekciju za


dodavanje i uklanjanje panela.

ShowPanels

Samo itanje

Ako hoete da prikaete panele, ovo svojstvo mora biti podeeno na


true.

Text

itanje/upis

Kada ne koristite panele, ovo svojstvo sadri tekst koji e se prikazati


na statusnoj liniji.

18

Dogaaji kontrole StatusBar

Nema mnogo novih dogaaja za statusnu liniju, ali ako crtate panel runo, dogaaj DrawItem je
od velike vanosti:
Ime

Opis

DrawItem

Deava se kada panel sa Owner Draw stilom treba ponovo


iscrtati. Morate prijaviti ovaj dogaaj ako elite sami da
crtate sadraj panela.

PanelClick

Deava se kada se izabere panel.

Klasa StatusBarPanel

Svaki panel u statusnoj linije jeste objekat klase StatusBarPanel. Ova klasa sadri informacije o
svim panelima kolekcije Panels. Moe se podeavati tekst, poloaj teksta u panelu, ikone ili stil
panela.
Ako elite sami da crtate panel, morate podesiti panel-ovo svojstvo Style na OwnerDraw i
obraditi dogaaj DrawItem kontrole StatusBar.
Primer kontrole StatusBar

Veba br. 28.


Izmeniemo postojei primer ListView kako bismo prikazali upotrebu kontrole StatusBar.
Stari projekat odnosno vebu pod brojem 27. Kontrola ListView. Snimite je u drugom folderu,
recimo C:\Temp\SoftIng\LecturesCode\Vezba28.
Otvorite VS .NET i kreirajte novi projekat. Izaberite Visual C# Projects
direktorijum unutar prozora Project Types:, i tip projekta Windows
Application u okviru prozora Templates: U okviru za tekst Location:
promenite putanju u C:\Temp\SoftIng\LecturesCode\Vezba28, i
ostavite podrazumevani tekst u okviru za tekst Name: Kontrola
StatusBar.
Da bi smo iskoristili prethodni primer, prvo ete obrisati iz ve postojeeg
projekta fajl Form1.cs tako to izaberete pomou desnog tastera mia
opciju Delete na selektovan fajl.

19

Zatim emo dodati fajl sa istim nazivom ali iz prethodnog primera


odnosno vebe 27 koje ste malo pre iskopirali.
Selektujte naziv projekta u prozoru Solution Explorera Kontrola
StatusBar, izaberete pomou desnog tastera mia opciju Add>Add
Existing Item... na selektovan naziv projekta. I birate naziv fajla
Form1.cs iz foldera C:\Temp\SoftIng\LecturesCode\Vezba28\
Kontrola StatusBar.
I ako ste uradili kako treba, moete otvoriti formu iz prethodnog
primera.
Ponimo sa promenom izgleda dijaloga:
Izbaciemo oznaku odnosno labelu, koju smo koristili za prikaz postojeeg direktorijuma, i
umesto toga ubaciti te informacije na panel statusne linije. Takoe, dodaemo jo jedan panel
za prikaz trenutnog reima prikazivanja liste:
Uklonite oznaku lblTrenutnaPutanja.
Dva puta pritisnite kontrolu StatusBar u okviru sa alatima da biste je ubacili u formular. Kontrola
e se automatski pripojiti donjoj ivici formulara i podesite njene osobine u prozoru properties.
Osobina (Properties)
Name
Text

Panels

Vrednost (Value)
sbInfo
izbriite
StatusBarPanel1
AutoSize: Spring; Ovo znai da e panel
deliti prostor statusne linije sa ostalim
panelima.

StatusBarPanel2
AutoSize: Contents; Ovo znai da e

panel menjati veliinu u zavisnosti od veliine


teksta koji sadri.

ShowPanels

MinWidth: 0
true

20

Dodavanje rutina za obradu dogaaja


Zavrili smo sa grafikim interfejsom i prelazimo na kod. Poinjemo sa podeavanjem trenutne
putanje u metodi FilujListView. Izbriite liniju koja podeava tekst u oznaci i umesto nje ubacite
sledei kod:

Prvi panel ima indeks 0, zato podeavamo svojstvo Text kao to smo podesili svojstvo Text
oznake. Drugi red koda podeava prikaz drugog panela, zato ima indeks 1. Inicijalizujemo tekst
drugog panela na List Pregled.
Na kraju, podeavamo rutine za obradu dogaaja CheckedChanged za etiri kontrole
RadioButton, tako da prikau tekst u drugom panelu:

21

Ovim zavravamo StatusBar primer. Ako pokrenete program, trebalo bi da dobijete neto nalik
ovome:

Kontrola TabControl

Kontrola TabControl obezbeuje lak nain organizovanja dijaloga u logike jedinice kojima se
moe pristupiti kroz jezike kartica na vrhu kontrole. Kontrola TabControl sadri kontrole
TabPages koje su sline grupnim okvirima, s tim to su neto kompleksnije:

Slika na prethodnoj strani pokazuje dijalog Options MS Worda 2000, u podrazumevanoj


konfiguraciji. Primetite dva reda koja sadre jezike kartica u vrhu kontrole. Pritiskom na bilo
koji od njih prikazae se drugaija selekcija kontrola u ostatku dijaloga. Ovo je dobar primer
kako grupisati informacije koje su u nekoj vezi jedna s drugom, tako olakavajui korisniku da
pronade eljenu informaciju.
22

Korienje kontrole TabControl je veoma lako. Jednostavno dodate jezike za kartice koje elite
prikazati u kolekciju TabPages, a zatim ubacujete ostale kontrole u odgovarajue strane.
Za vreme izvravanja programa, moete se kretati kroz kartice koristei svojstva kontrole.

Svojstva kontrole TabControl

Osobine kontrole TabControl se uglavnom koriste za podeavanje izgleda kontejnera u kome se


nalaze kontrole TabPages, tj. za izgled kartica:
Ime osobine

Dostupnost

Opis

Alignment

itanje/upis

Kontrolie gde se na kontroli pojavljuju jezici kartica. Podrazumeva


se da su na vrhu.

Appearance

itanje/upis

Kontrolie kako su prikazani jezici kartica. Mogu biri kao dugme ili
ravni.

HotTrack

itanje/upis

Ako je ovo svojstvo podeeno na true, izgled jezika kartice se menja


kako pokaziva mia prelazi preko njega.

Multiline

itanje/upis

Ako je ovo svojstvo podeeno na true, mogue je imati nekoliko


redova sa jezicima kartica.

RowCount

Samo itanje

Sadri broj redova sa jezicima kartica koji su trenutno prikazani.

Selectedlndex

itanje/upis

Vraa ili podeava indeks trenutno izabranog jezika kartice.

TabCount

itanje/upis

Sadri ukupan broj kartica.

TabPages

itanje/upis

Ovo je kolekcija objekata TabPages. Koristite ovu kolekciju za


dodavanje ili uklanjanje kartica.

Rad sa kontrolom TabControl

Kontrola TabControl ponaa se malo drugaije u odnosu na ostale kontrole koje smo do sada
videli. Kada dovuete kontrolu na formular, videete sive etvorouglove, koji ne izgledaju kao
kontrole koje vidimo na slici ekrana iznad. Takoe, videete ispod panela Properties, dva
dugmeta koja izgledaju kao hiperveze sa natpisima Add Tab i Remove Tab.
Ako pritisnete dugme Add Tab, ubaciete novu karticu u kontrolu, a kontrola e poeti da lii na
sebe. Oigledno, izbaciete karticu iz kontrole ako pritisnete dugme Remove Tab.
Ova procedura je obezbedena radi lakeg korienja kontrole. Ako, sa druge strane, elite da
promenite ponaanje ili stil kartice, trebalo bi da koristite dijalog TabPages. Do ovog dijaloga
dolazite kada u panelu sa svojstvima izaberete TabPages.
Svojstvo Tab Pages je i kolekcija koju moete koristiti za pristup pojedinanim stranicama
kontrole. Kreiraemo primer koji demonstrira osnovne karakteristike kontrole TabControl.

23

Primer kontrole TabControl

Veba br. 29.


Napravite novi projekat konzolne aplikacije birajui File | New | Project... iz menija:
Izaberite Visual C# Projects direktorijum unutar prozora Project Types:, i tip projekta
Windows Application u okviru prozora Templates: U okviru za tekst Location: promenite
putanju u C:\Temp\SoftIng\LecturesCode\Vezba29 (ovaj e direktorijum biti automatski
napravljen ukoliko ve ne postoji), i ostavite podrazumevani tekst u okviru za tekst Name:
Kontrola TabControl.
Otvorite paletu Properties i za kontrolu forme podesite sledee osobine:
Osobina (Properties)
Name
Text
StartPosition
FormBorderStyle
Size

Vrednost (Value)
fclsMain
Kontrola TabControl
CenterScreen
FixedSingle
298; 305

Dodajte kontrolu TabControl, i podesite sledee osobine:


Osobina (Properties)
Name
TabPages
Location
Size

Vrednost (Value)
tbcKontrola
TabControl1
Text: Prvi Tab
TabControl2
Text: Drugi Tab
0; 0
280; 216

Na prvoj TabPages odnosno TabControl1 postavite jednu kontrolu ComboBox i jednu kontrolu
dugmeta Button i podesite joj osobine:
Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
btnMessages
Prikai poruku
76; 84
120; 23

Na drugoj TabPages odnosno TabControl2 postavite jednu kontrolu TextBox i podesite joj
osobine:
Osobina (Properties)
Name
Text
Location
Size

Vrednost (Value)
txtMessage
obriite
56; 56
152; 20
24

Dodavanje rutine za obradu dogaaja

Sada smo spremni da pristupamo kontrolama. Ako pokrenete kod u ovom obliku, videete kartice
prikazane kako treba. Ostaje jedino da demonstriramo rad kontrole - kada korisnik pritisne na
Show Message dugme na jednoj kartici, prikazae se tekst koji je unet u tekstualni okvir na
drugoj kartici. Prvo, dodajemo rutinu za obradu dogaaja Click. Dva puta pritisnite dugme na
prvoj kartici i dodajte sledei kod:

Kontroli na jednoj stranici pristupamo kao i svakoj drugoj kontroli. Dolazimo do svojstva Text
kontrole TextBox i prikazujemo je u okviru za poruke.
Ve smo videli da je mogue izabrati samo jedno radio dugme na formularu (ukoliko ih ne stavite
u odvojene grupne okvire). Kartice kontrole TabControl ponaaju se isto kao i grupni okviri, tako
da je mogue imati razliite grupe radio dugmadi na razliitim karticama ove kontrole, bez
korienja grupnih okvira.
Jo jednu stvar morate da znate kada radite sa kontrolama TabControl - koja kartica je trenutno
prikazana. Dve osobine mogu pomoi: SelectedTab i Selectedlndex. Kao to imena govore,
svojstvo SelectedTab vraa objekat TabPage, ili null ukoliko nijedna kartica nije izabrana.
Svojstvo Selectedlndex vraa indeks kartice, ili -1 ukoliko nijedna kartica nije izabrana.

Saetak

U ovom predavanju videli smo najee koriene kontrole za izradu Windows aplikacija i kako se
one mogu koristiti za pravljenje jednostavnih ali monih korisnikih interfejsa. Opisali smo
osobine i dogaaje tih kontrola i dali primere njihove upotrebe.

25

U ovom predavanju obradili smo sledee kontrole:


Label
Button
RadioButton
CheckBox
ComboBox
ListBox
ListView
GroupBox
RichTextBox
StatusBar
ImageList
TabControl

U sledeem predavanju pogledaemo kompleksnije kontrole kao to su meniji i palete alata.


Koristiemo ih za razvoj Windows aplikacija koje podravaju rad sa vise dokumenata {MultiDocument Interface - MDI). Takoe, pokazaemo kako se kreiraju korisnike kontrole koje
kombinuju funkcionalnost jednostavnih kontrola, a koje smo obradili u ovom predavanju.

26

You might also like