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 na in 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, budu i 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. Ograni enja zapravo ne postoje - .NET okruenje daje vam mogu nost 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 ra unaru. 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) pole emo. 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 odre eni 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 izvu i 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 po etka 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 odli no se slau sa njim. Ovo je upro eno kori enjem modula Windows formulara unutar .NET okruenja, koji u stvari ini biblioteka k ontrola (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 mo an sistem generisanja Web sadraja i to dinami ki, dozvoljavaju i 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 na in izrade raznovrsnih distribuiranih aplikacija. Koristei Web servise preko Interneta moemo razmenjivati bilo koju vrstu podataka, koriste i prostu sintaksu, ne vode i 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), po ev 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 koriste i 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 omogu uje pametnu detekciju greaka i sugerie odgovaraju i kod na pravom mestu dok ga unosimo. VS sadri i dizajnerske alate za aplikacije koje uklju uju 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 odgovaraju i kod postoje im 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 omogu uje i jednostavniju distribuciju i prilagoavanje projekata klijentima, kako bi ih oni lake koristili ili instalirali. VS omogu uje 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 ose aj 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 pokre ete 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 na i 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 V \t \v \" \\ 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. Horizontalan tabulator. Daje znak tabulatora. 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 sbyte byte short ushort int uint long ulong pseudonim za System.SByte System.Byte System.Intl6 System.UIntl6 System.Int32 System.UInt32 System.Int64 System.UInt64 dozvoljene vrednosti ceo broj izmeu -128 i 127. ceo broj izmeu 0 i 255. ceo broj izmeu -32768 i 32767. 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 float double decimal Pseudonim za System. Single System.Double System.Decimal Minm 0 0 0 Maxm 224 253 296 Mine -149 -1075 -26 Maxe 104 970 0 Pribl. min vrednost 1.5x10-45 5.0x10124 1.0x10-28 Pribl. max vrednost 3.4x1038 1.7x10308 7.9x1028

Pored brojevnih tipova postoje jo tri prosta tipa:


Tip char bool string Pseudonim za System.Char System.Boolean 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
Boolean Byte Char Decimal Double Integer Long Object Short String

Prefiks
bln byt chr dec dbl int lng obj sho str

Primer vrednosti
blnUlogovan bytGodiste chrLozinka decProdato dblRezultatIzracunavanja intBrojacPetlje lngIdKupca objWord shoTotalnaVrednost strIme

Tabela 4.2. Prefiksi promenljivih po podruju vaenja

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

Prefiks
g m (no prefix)

Primer vrednosti
g_strSnimiPutanju m_blnPromenaVrednosti

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)
bool int,uint, long, ulong uint,ulong long, ulong ulong float double decimal char string

Kategorija
logika celobrojna celobrojna celobrojna celobrojna realna realna realna znakovna niz znakova

Sufiks
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 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
\` \" \\ \0 \a

Znak koji pravi


jednostruki navodnik dvostruki navodnik obrnuta kosa crta nula alarm(pravi pitanje)

Vrednost znaka u unicode-u


0x0027 0x0022 0x005C 0x0000 0x0007

Tabela 4.4. Escape sekvence

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

Znak koji pravi


unazad za jedan znak prelazak na sledeu stranicu novi red prenos u novi red horizontalni tabulator vertikalni tabulator

Vrednost znaka u unicode-u


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

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
binarni binarni binarni binarni binarni unarni unarni

Primer izraza
var1=var2+var3; var1=var2-var3; var1 = var2 * var3; var1 = var2 / var3 var1 = var2 % var3 var1 = +var2 var1 = -var2

Rezultat
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 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
unarni unarni unarni unarni

Primer izraza
var1=++var2 var1=--var2 var1=var2++ var1=var2-var1 var2 var1 var2 var1 var2 var1 var2 je je je je je je je je

Rezultat
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 o it e da su izrazi prviBroj + drugiBroj i sli no, 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
binarni binarni binarni binarni binarni binarni

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

Rezultat
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

= += -= *= /= %=

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 slede i: 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 izra unava prvi, to zna i 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
Najvii

Operator
++, (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 tako e koriste i pri kategorisanju objekata .NET okruenja. Najvei deo tih objekata su definicije tipova, kao to su recimo prosti tipovi (System. Int32 i sli no). C# kod se podrazumevano sadri u globalnim imenovanim prostorima. To zna i 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 klju nu 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, tako e koriste i klju nu re namespace. Ugnedeni imenovani prostori se pozivaju preko svoje hijerarhije, opet koriste i 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 { } } 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 } // 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
binarni binarni binarni binarni binarni binarni

Primer izraza
var1=var2== var3; var1=var2!= var3; var1=var2< var3; var1=var2>var3; var1=var2<= var3; 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
unarni binarni

Primer izraza
var1=!var2; 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).

binarni

var1=var21 var3;

binarni

var1=var2 var3;

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
binarni

Primer izraza
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)

||

binarni

var1=var2||var3;

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 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

Grananje

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 obezbe uje 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 pore enja, 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 identi an onome pre njega. Pa ipak, ovaj kod je mnogo laki za itanje. Kada pravite viestruka pore enja 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 slede i 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 upore uju skrivene od nas u vreme poreenja. Konstantne promenljive se deklariu kori enjem 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 slu aju 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 pla ena 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 ska e 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 slede i 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 slede i 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 razli itih 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 presko ite 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 ve a 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. Me utim, 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 odre ene 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 teku u 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 prili no 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 slede eg 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 slede u 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 ra unar 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 zna aja 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 uvla enja redova u kodu - ceniete to znanje kasnije. VS e uraditi dosta toga za nas, ali nije lose da se tokom pisanja jo malo uvla e 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) ve a 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 ve i 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 ne e 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.

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.

ta je dogaaj?

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.

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

Definisanje 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.

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():

Kako to radi

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 Meni bi trebalo da izgleda kao na sledeoj slici: Text &Print Print Pre&view... Page Set&up... E&xit

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 MinMargins.Da bismo proitali margine, koristimo svojstvo 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:


using System.Drawing.Printing;

da

uvrstimo

imenovani

prostor

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 AllowVectorFonts Opis
Boolean vrednost koja definie da li vektorski fontovi mogu da budu izabrani u listi fontova. 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. 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.

AllowVerticalFonts

FixedPitchOnly MaxSize MinSize

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. Izbor boje nije podrazumevano prikazan u dijalogu. Ako elite da korisnik izabere boju fonta u font dijalogu, morate da postavite svojstvo ShowColor na true. 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. 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.

ShowColor

ShowEffects

AllowScriptChange

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
AllowFullOpen

Opis
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. Podeavanje svojstva FullOpen na true pre nego to se dijalog prikae, automatski otvara dijalog sa posebnim podeavanjima boja. Postavljanjem ovog svojstva na true pokazuju nam se sve dostupne boje u listi osnovnih boja. Sa svojstvom CustomColors moete podesiti niz posebnih boja, i moete proitati posebne boje koje je korisnik podesio. Podeavanjem svojstva SolidColorOnly na korisnik moe samo da izabere osnovne boje. true,

FullOpen

AnyColor

CustomColors SolidColorOnly

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
Anchor BackColor Bottom Dock Enabled ForeColor Height

Dostupnost
itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis

Opis
Ovo svojstvo definie ponaanje kontrole kada kontejner koji sadri kontrolu menja svoju veliinu. Posle tabele nalazi se detaljno objanjenje ove osobine. Boja pozadine 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. 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. Boja prednjeg plana kontrole. Udaljenost od vrha do dna kontrole.

Ime osobine
Left Name Parent Right TabIndex Tabstop Tag Top Visible Width

Dostupnost
itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis

Opis
Udaljenost leve ivice kontrole od leve ivice prozora. Ime kontrole. Ime se koristi za pristup kontroli u kodu. Roditelj kontrole. Udaljenost desne ivice kontrole od leve ivice prozora. Redosled promene kontrola u kontejneru koji ih dri prilikom pritiska na taster Tab. Odreuje da li kontrola moe biti dostupna pritiskanjem tastera Tab. Ovu vrednost ne koristi sama kontrola, ve slui programerima za smetanje informacija o kontroli. Ovoj osobini moe se dodeliti jedino vrednost u formi stringa. Udaljenost gornje ivice kontrole od vrha prozora. Odreuje da li je kontrola vidljiva u toku izvravanja programa. 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 veli inu, 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 veli inu 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
Click

Opis
Deava se kada se pritisne na kontrolu. Ovaj dogaaj e se takoe desiti kada se pritisne taster Enter. 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. Deava se kada se zavri operacija prevlaenja i sputanja. Drugim reima, kada se neki objekat prevue do kontrole, a onda se pusti taster mia. Deava se kada dovueni objekat ude u granice kontrole. Deava se kada dovueni objekat naputa granice kontrole. Deava se kada dovueni objekat prelazi preko kontrole. Deava se kada se taster pritisne dok kontrola ima fokus. Ovaj dogaaj uvek ide pre dogaaja KeyPress i KeyUp. 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. Deava se kada se taster pusti dok kontrola ima fokus. Ovaj dogaaj uvek ide posle dogaaja KeyDown i KeyPress. Deava se kada kontrola primi fokus. Nemojte koristiti ovaj dogaaj za validaciju kontrole - umesto toga koristite dogaaje Validating ili Validated. Deava se kada kontrola izgubi fokus. Nemojte koristiti ovaj dogaaj za validaciju kontrole - umesto toga koristite Validating ili Validated dogaaje. 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. Deava se kontinuirano dok mi prelazi preko kontrole. Deava se kada je pokaziva mia na kontroli i kada se taster mia oslobodi. Deava se kada se kontrola iscrtava. 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. 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.

Doubleclick DragDrop DragEnter DragLeave DragOver KeyDown

Key Press

KeyUp

GotFocus

LostFocus

MouseDown MouseMove MouseUp Paint Validated

Validating

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. Obi no se sastoji od stavljanja kontrole u formular, dvostrukog pritiska na kontrolu za dodavanje koda za doga aj 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, napravi emo 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
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. Pominjemo ovu osobinu ovde, iako je ona izvedena iz klase Control, zato to je od velike vanosti za dugme. Podeavanje Enabled osobine na false zna i da dugme postaje sivo i nita se ne deava kada se pritisne na njega. Omoguava biranje slike (bitmape, ikone itd.) koja e se pojaviti na dugmetu. Uz pomo ove osobine moete da izaberete poloaj slike na dugmetu.

FlatStyle

itanje/upis

Enabled

itanje/upis

Image ImageAlign

itanje/upis itanje/upis

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, ne e 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 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. Vrednost (Value) fclsMain Kontrola Button CenterScreen Microsoft Sans Serif, Regular, 8, Central European FixedSingle 262; 150

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 za Button2 Osobina (Properties) Name Text Cursor Image ImageAlign Location Size za Button3 Osobina (Properties) Name Text Cursor Location Size btnOk &OK Hand 88; 72 75; 23 Vrednost (Value) 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 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

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 na ina. 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 doga aj Click. Unesite slede i kod u telu Click doga aja.

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 naj e e 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
BorderStyle DisabledLinkColor FlatStyle Image ImageAlign LinkArea LinkColor Links

Dostupnost
itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis

Opis
Omoguava da izaberete date ivice oznake. Podrazumeva se da nema ivica. Samo za LinkLabel: boja koju e kontrola LinkLabel imati kada je korisnik pritisne. 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. Omoguava biranje slike (bitmape, ikone itd.) koja e se pojaviti na oznaci. Odreuje poloaj slike na oznaci. Samo za LinkLabel: opseg teksta koji e biti prikazan kao veza. Samo za LinkLabel: Boja hiperveze. 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. Samo za LinkLabel: obavetava da li je neka hiperveza prethodno poseena ili ne. Tekst koji se pojavljuje u oznaci. Odreuje poloaj teksta na kontroli.

itanje/upis

LinkVisited Text TextAlign

itanje/upis itanje/upis itanje/upis

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
Causes Validation CharacterCasing

Dostupnost
itanje/upis itanje/upis

Opis
Odreuje da li e kontrola TextBox menjati slova u mala ili velika. Mogue vrednosti su: Lower: sva uneta slova bie konvertovana u mala slova. Q Normal: nee biti nikakvih promena. 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. Pokazuje da li je ovo kontrola sa vise redova. Kontrola sa vise redova moe da prikae vise redova teksta. 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. Logika vrednost koja pokazuje da li je tekst samo za itanje. Odreuje da li tekst u vise redova treba da ima traku za pomeranje. Tekst koji je izabran u okviru za tekst. 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. Poetak izabranog teksta u okviru za tekst. Odreuje da li u okvirima za tekst sa vise redova, re koja premauje irinu kontrole treba automatski da bude prebaena u novi red.

MaxLength

itanje/upis

MultiLine PasswordChar Readonly ScrollBars SelectedText

itanje/upis itanje/upis itanje/upis itanje/upis

itanje/upis

SelectionLength SelectionStart Wordwrap

itanje/upis

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 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.

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.

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 pet kontrola TextBox, redom: za TextBox1 Osobina (Properties) Name Text Multiline Location Size txtIme False 104; 16 296; 20 Vrednost (Value) Vrednost (Value) fclsMain Primer TextBox-a Microsoft Sans Serif, Regular, 8, Central European FixedSingle CenterScreen 520; 432

14

za TextBox2 Osobina (Properties) Name Text Multiline ScrollBars Location Size za TextBox3 Osobina (Properties) Name Text Multiline Location Size za TextBox4 Osobina (Properties) Name Text Multiline Location Size za TextBox5 Osobina (Properties) Name Text Multiline ReadOnly ScrollBars Location Size txtIzlaz True True Vertical 0; 296 512; 104 Vrednost (Value) txtGodiste False 104; 222 72; 20 Vrednost (Value) txtZanimanje False 104; 192 296; 20 Vrednost (Value) txtAdresa True Vertical 104; 46 296; 136 Vrednost (Value)

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 za Button2 Osobina (Properties) Name Text Cursor CausesValidation Location Size za Button3 Osobina (Properties) Name Text Cursor Location Size btnIzlaz &Izlaz Hand 416; 128 75; 23 Vrednost (Value) btnHelp &Help Hand false 415; 48 75; 23 Vrednost (Value) btnOK &OK Hand 415; 16 75; 23 Vrednost (Value)

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
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. 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. Odreuje poloaj radio dugmeta. Svojstvo moe biti podeeno na left, middle ili right (levo, u sredini, desno). Pokazuje status kontrole. Ako je kontrola potvrena, onda je ovo svojstvo podeeno na true, odnosno false u suprotnom.

Appearance

itanje/upis

AutoCheck

itanje/upis

CheckAlign Checked

itanje/upis

itanje/upis

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
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. 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.

CheckChanged

Click

Kao to pretpostavljate, osobine i dogaaji ove kontrole su slini onima za RadioButton, ali tu su i dve nove: Ime osobine Dostupnost Opis
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. Ako je ovo svojstvo podeena na false, korisnik nee modi da izmeni status kontrole na Indeterminate. Moete, meutim, izmeniti status u kodu.

Svojstva kontrole CheckBox

CheckState

itanje/upis

ThreeState

itanje/upis

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
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. 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.

Dogaaji kontrole CheckBox

CheckedChanged

CheckedStateChanged

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 grpPol Pol 104; 216 296; 56 Vrednost (Value)

5. Dodajte na formu u GroupBox-u dve kontrole RadioButton i promenite sledea svojstva: za RadioButton1 Osobina (Properties) Name Text hecked Location Size za RadioButton2 Osobina (Properties) Name Text hecked Location Size Vrednost (Value) rdoZensko ensko False 152; 24 104; 24 rdoMusko Muko True 24; 24 104; 24 Vrednost (Value)

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

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.

Kontrola RichTextBox

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
CanRedo CanUndo RedoAc t i onName DetectUrls Rtf SelectedRtf

Dostupnost
Samo itanje

Opis
Vrednost ove osobine je true, ako neto to je poniteno moe biti ponovljeno; u suprotnom je false. Vrednost ove osobine je true, ako je mogue izvriti akciju Undo na obogaeni okvir za tekst; u suprotnom je false. Ovo svojstvo sadri ime akcije koja e biti koriena da bi se ponovo uradila neka prethodno ponitena radnja u obogaenom okvira za tekst. Podesite ovu osobinu na true ako elite da kontrola detektuje URL adrese i da ih formatira (podvue, kao u itau). Ovo odgovara svojstvu Text, s tim to je tekst u RTF formatu. 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. Kao i SelectedRtf, moete dobiti ili podesiti izabrani tekst. Za razliku od prethodne osobine, pri kopiranju tekst ne zadrava svoj format. Ovo svojstvo predstavlja nain poravnavanja izabranog teksta. Moe biti Center, Left ili Right (centar, levo ili desno). 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. Koristite ovu osobinu da odredite za koliko piksela treba uvui simbol za nabrajanje. Doputa vam da menjate boju izabranog teksta. Doputa vam da menjate font izabranog teksta. Uz pomo ove osobine moete podesiti ili saznati duinu izabranog teksta. Ovo svojstvo sadri informacije o izabranom delu. Red e vam da li je izabran neki OLE objekat ili je izabran samo tekst. 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.

Samo itanje

Samo itanje itanje/upis itanje/upis

itanje/upis

SelectedText SelectionAlignment SelectionBullet Bulletlndent SelectionColor SelectionFont SelectionLenght SelectionType ShowSelectionMargin UndoAc t i onName SelectionProtected

itanje/upis

itanje/upis

itanje/upis

itanje/upis itanje/upis itanje/upis itanje/upis Samo itanje itanje/upis Samo itanje

itanje/upis

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.

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 Protected Opis
Ovaj dogaaj se alje kada korisnik pritisne vezu unutar teksta. Ovaj dogaaj se alje kada korisnik pokua da promeni tekst koji je oznaen kao zatien. 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.

Dogaaji kontrole RichTextBox

SelctionChanged

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
btnBold &Bold 71; 8

Button2
btnItalic &Italic 159; 8

Button3
btnUnderline &Underline 247; 8

Button4
btnCentar &Centar Hand 335; 8 75; 23

Button5
bthLoad &Load 155; 240

Button6 Button7
btnSave &Save 251; 240 btnIzlaz &Izlaz 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 rtfText 0; 64 480; 168 Vrednost (Value)

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.

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.

Kontrole ListBox i CheckedListBox

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

Svojstva kontrole ListBox

Dostupnost
itanje/upis

Opis
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. U okvirima sa vise kolona, ovo svojstvo odreuje irinu kolona. Kolekcija Items sadri sve elemente liste. Koristite ovu osobinu za dodavanje ili izbacivanje elementa. U okvirima sa vise kolona, ovo svojstvo odreuje irinu kolona. Ovo svojstvo je kolekcija koja sadri indekse izabranih elemenata, pri emu indeksiranje poinje od nule. 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.

ColumnWidth Items MultiColumn Selectedlndices Selectedltem Selectedltems

itanje/upis Samo itanje itanje/upis Samo itanje itanje/upis Samo itanje

SelectionMode

itanje/upis

Sorted

itanje/upis

Ako podesite ovu osobinu na true, kontrola ListBoxce sortirati elemente po abecednom redu.

16

Ime osobine

Dostupnost

Opis
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. Samo za kontrolu CheckedListBox: ovo svojstvo sadri sve indekse elemenata koji su potvreni ili koji imaju neodreen status. Samo za kontrolu CheckedLi s tBox: ovo je kolekcija koja sadri sve elemente koji su potvreni ili koji imaju neodreen status. Samo za kontrolu CheckedListBox: ako je ovo svojstvo podeeno na true, element menja stanje kad god korisnik pritisne na njega. Samo za kontrolu CheckedListBox: podeavanjem ove osobine moete birati da li e polja za potvrdu biti ravna ili normalna.

Text

itanje/upis

Checkedlndicies CheckedItems CheckOnClick

Samo itanje Samo itanje itanje/upis

ThreeDCheckBoxes

itanje/upis

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 GetSelected SetSelected ToString GetltemChecked GetltemCheckState SetltemChecked
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. Vraa vrednost koja pokazuje da li je element izabran ili nije. Podeava da element bude izabran, ili brie element iz liste izabranih elemenata. 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.

Metode kontrole ListBox

Opis

SetltemCheckState

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
ItemCheck SelectedlndexChanged

Opis
Samo za kontrolu CheckedListBox: deava se kada se menja stanje elementa. 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 za ChekedListBox1 Osobina (Properties) Name CheckOnClick Vrednost (Value) chkListaIzbora True jedan dva tri etiri pet est sedam osam devet 8; 8 136; 184 Vrednost (Value) btnPrebaci Prebaci 152; 80 75; 23

Items

Location Size 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


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.

Kontrola ComboBox

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
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. Pokazuje da li je lista prikazana ili nije. Ako podesite ovu osobinu na true, lista e se prikazati. Kolekcija koja sadri sve elemente liste iz kombinovanog okvira. Podeavanjem ove osobine na broj vei od nule, odreujete maksimalan broj karaktera koji je mogue uneti u tekstualni deo kontrole. Pokazuje indeks trenutno izabranog elementa liste. Pokazuje trenutno izabrani element liste. Predstavlja tekst koji je izabran u tekstualnom delu kontrole. Predstavlja indeks prvog karaktera dela teksta koji je izabran u tekstualnom delu kontrole. Predstavlja duinu izabranog teksta u tekstualnom delu kontrole. Ako podesite ovu osobinu na true, kontrola e sortirati elemente liste po abecednom redu. 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

DropDownStyle

itanje/upis

DroppedDown Items MaxLength Selectedlndex Selectedltem SelectedText SelectionStart SelectionLength Sorted

itanje/upis Samo itanje itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis

Text

itanje/upis

Dogaaji kontrole ComboBox


Kada se promeni izbor;

Postoje tri osnovne akcije za koje elite da znate kada se dese u kombinovanom okviru:

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 SelectedlndexChanged KeyDown KeyPress KeyUp TextChanged

Opis
Deava se kada se prikae deo sa okvirom sa listom. Deava se kada se umesto jednog elementa u listi izabere neki drugi element. Ovi dogaaji deavaju se kada se pritisne taster dok tekstualni deo kontrole ima fokus. Pogledajte objanjenja ovih dogaaja za tekstualni okvir. 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

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:

Dodavanje rutina za obradu dogaaja

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:

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.

Kontrola ListView

Svojstva kontrole ListView


Ime osobine Dostupnost Opis
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. 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. 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. 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. 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. Ova dva svojstva daju pristup kolekcijama koje sadre indekse i elements koji su potvreni. Kontrola ListView moe imati kolone. Ovo svojstvo obezbeuje pristup kolekciji kolona, kroz koju moete dodavati ili uklanjati kolone. Ovo svojstvo sadri element koji ima fokus. Ako nita nije izabrano, vrednost je null.

Activation

itanje/upis

Alignment

itanje/upis

AllowColumn Reorder

itanje/upis

AutoArrange

itanje/upis

CheckBoxes
Checkedlndices Checkedlterns Columns Focusedltem

itanje/upis

Samo itanje Samo itanje Samo itanje

Ime osobine
FullRowSelect

Dostupnost
itanje/upis

Opis
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. 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. Moete stila: 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.

GridLines

itanje/upis

HeaderStyle

itanje/upis

HoverSelection Items LabelEdit LabelWrap LargelmageList MultiSelect Scrollable Selectedlndices Selectedltems SmallImageList

itanje/upis Samo itanje itanje/upis itanje/upis itanje/upis itanje/upis itanje/upis Samo itanje Samo itanje itanje/upis

Kada je ovo svojstvo podeeno na true, korisnik moe izabrati element postavljanjem mia na element. 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. Sadri indekse izabranih elemenata. Sadri izabrane elemente. Ovo svojstvo sadri kontrolu ImageList u kojoj se nalaze slike. Ove slike se mogu koristiti kada je svojstvo View podeeno na Smalllcon. Kontrola ListView moe sortirati elemente koje sadri. Postoje tri razliita naina: Ascending: po rastuem redosledu. Descending: po opadajuem redosledu. None: nema sortiranja. Kontrola ImageList sadri maske za slike koje se koriste za prekrivanje slika iz kolekcija LargelmageList i SmalllmageList, u cilju prikazivanja trenutnog stanja. Vraa element koji se nalazi na vrhu liste. 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.

Sorting

itanje/upis

StatelmageList Topitern

itanje/upis Samo itanje

View

itanje/upis

Za kompleksnu kontrolu kakva je ListView, postoji iznenaujue mali broj metoda. Sve su opisane u sledeoj tabeli: Ime Opis
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. Kompletno uklanja sve elemente i kolone kontrole ListView. Ovu metodu pozivate posle metode BeginUpdate. Kada je pozovete, svi elementi e biti iscrtani u kontroli ListView. Kada pozovete ovu metodu, lista e se pomeriti do onog elementa iji je indeks prosleen metodi. Vraa element u listi koji se nalazi na poziciji x, y.

Metode klase ListView

BeginUpdate

Clear EndUpdate EnsureVisible GetltemAt

Dogaaji kontrole ListView


Ime
AfterLabelEdit BeforeLabelEdit ColumnClick ItemActivate

Sledea tabela opisuje dogaaje koje moete pozivati za kontrolu ListView: Opis
Ovaj dogaaj nastaje posle ureivanja oznake. Ovaj dogaaj nastaje pre nego to korisnik zapone ureivanje oznake. Ovaj dogaaj nastaje kada je kolona pritisnuta. 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 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

Kontrola ImageList

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 btnNazad Nazad 240; 256 75; 23 Vrednost (Value)

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) Name Text Location Size 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

Vrednost (Value) groPregledMod Pregled mod 424; 32 120; 128

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 Images

ImageList1
ilMaleIkone 16; 16

ImageList2
ilVelikeIkone 32; 32

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


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 Dobijate formular kao na slici: Vrednost (Value) lwFajloviFolderi List ilVelikeIkone ilMaleIkone true 16; 32 558; 325

12

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:

Dodavanje rutina za obradu dogaaja

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:

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:

Kontrola StatusBar

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
Backgroundlmage Panels ShowPanels Text

Dostupnost
itanje/upis itanje/upis Samo itanje itanje/upis

Opis
Mogue je dodeliti sliku statusnoj liniji, koja e se iscrtati u pozadini. Ovo je kolekcija panela u statusnoj liniji. Koristite ovu kolekciju za dodavanje i uklanjanje panela. Ako hoete da prikaete panele, ovo svojstvo mora biti podeeno na true. 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
DrawItem PanelClick

Opis
Deava se kada panel sa Owner Draw stilom treba ponovo iscrtati. Morate prijaviti ovaj dogaaj ako elite sami da crtate sadraj panela. 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 Vrednost (Value) sbInfo izbriite StatusBarPanel1 AutoSize: Spring; Ovo znai da e panel
deliti prostor statusne linije sa ostalim panelima.

Panels

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 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:

Kontrola TabControl

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
Alignment Appearance HotTrack Multiline RowCount Selectedlndex TabCount TabPages

Dostupnost
itanje/upis itanje/upis itanje/upis itanje/upis Samo itanje itanje/upis itanje/upis itanje/upis

Opis
Kontrolie gde se na kontroli pojavljuju jezici kartica. Podrazumeva se da su na vrhu. Kontrolie kako su prikazani jezici kartica. Mogu biri kao dugme ili ravni. Ako je ovo svojstvo podeeno na true, izgled jezika kartice se menja kako pokaziva mia prelazi preko njega. Ako je ovo svojstvo podeeno na true, mogue je imati nekoliko redova sa jezicima kartica. Sadri broj redova sa jezicima kartica koji su trenutno prikazani. Vraa ili podeava indeks trenutno izabranog jezika kartice. Sadri ukupan broj kartica. Ovo je kolekcija objekata TabPages. Koristite ovu kolekciju za dodavanje ili uklanjanje kartica.

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.

Rad sa kontrolom 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 txtMessage obriite 56; 56 152; 20 24 Vrednost (Value)

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