You are on page 1of 12

0.

UVOD
.net framework (za Microsoft Visual C# 2005 je 2.0) okruenje u kojem se
izvrava na program. Da bi program koji smo napravili proradio na nekom raunaru
mora da ima instaliran .net framework. Ovo je komponenta koja nam omoguuje da
ne razmiljamo koji operativni sistem korisnik ima, nego samo da se posvetimo
reavanju problema. Program koji razvijemo e raditi na Windows 98,Windows
2000,Windows 2003, Windows XP, uz prilagoavanje i na Windows Mobile Edition
(postoje mobilni sa ovim operativnim sistemom) i Windows CE (namenjen handheld raunarima)
Solution, Projekat Kada u Microsoft Visual Studiu kreiram novi Projekat on e
kreirati i Solution. Dakle na vrhu je Solution, a on se sastoji iz jednog ili vie
Projekata. Ono to treba da primetite je da postoji file Program.cs, a u njemu red
Application.Run(new Form1());

Ovim se zapravo odreuje od koje forme se startuje program.


Objektno orijentisano programiranje kada u Microsoft Word-u oznaite deo
teksta i pritisnite desni klik moete da vidite neke osobine koje moete da promenite
(Font, Paragraf), kao i neke akcije koje moete da uradite (Cut, Copy). E pa to je ono
od ega se sastoji jedan objekat Osobine ili Properties i Metode. Na primer
TextBox1.Text pristupam tekst osobini objekta TextBox1, frm.ShowDialog()
izvravam metodu-funkciju koju sadri objekat frm.
Programiranje pokrenuto dogaajem kada pravimo program mi zapravo piemo
ta da se uradi na neki dogaaj. Recimo kada korisnik pritisne dugme (Button) treba
da se prikae poruka. Na dvostruki klik na button u kodu e se pojaviti sledee
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("ja radim!");
}
Dodatno objanjenje za ovo je sledee. Ako mi pravimo program u
fajlu Form1.cs, automatski se pravi Form1.Designer.cs koji sadri
program koji realizuje one stvari koje smo mi napravili u dizajneru.
Konkretno kada smo kliknuli na button1 u Form1.Designer.cs on je
dodao sledei red
this.button1.Click += new System.EventHandler(this.button1_Click);
(sa this pristupam klasi koju pravim, mi piemo kod u klasi Form1,
dakle sa this pristupamo svim njenim elementima i metodama.)

Ovim se redom kae, kada se desi button1 click dogaaj pozovi metodu
koja se zove button1_Click. Dakle ovo smo mogli uraditi i bez pomoi
dizajnera.
Kako moemo spreiti da se dalje izvrava button1_Click dogaaj?
Dovoljno je napisati:
this.button1.Click -= new System.EventHandler(this.button1_Click);
Postoji jo jedan nain da napravimo event proceduru. Oznaimo
objekat, recimo button, zatim u prozoru Properties pritisnemo
ikoninicu sa izlomljenom utom linijom i dobiemo spisak dogaaja.
Napravimo dvostruki klik pored dogaaja koji nas interesuje i
kreirali smo funkciju.

Class Postoje dva bitna termina u objektno-orijentisanom programiranju klasa i


objekat. Najbolje poreenje jeste projekat zgrade i sama zgrada. Klasa je nacrt kako
neki objekat treba da izgleda, a objekat je jedna realizacija te zamisli. Potrebno je da
primetite da Form1 klasa. Dobra praksa je da novu klasu dodate u zaseban fajl koji
ete nazvati po imenu klase.
class Osoba
{
public string strIme;
public string strPrezime;
public Osoba()
{ }
}
class Student:Osoba
{
public int intBrojPoloznih = 0;
private decimal decProsek;
public Student()
{
}
public string VratiOpis()
{
return this.strIme + " " + strPrezime
+ " , a prosek je " + decProsek.ToString();
}

public decimal Prosek


{
get
{
return decProsek;
}
set
{
decProsek = value;
}
}
}
U ovom primeru postoji vie stvari na koje treba da primetite
Konstruktor
public Student()
{
}
Pokree se prilikom instanciranja jednog objekta. U trenutku
pravljenja jednog objekta od klase prvo e se pokrenuti njen
konstruktor.
Metoda klasa moe da ima neke funkcije. Na primer
public string VratiOpis()
{
return this.strIme + " " + strPrezime
+ " , a prosek je " + decProsek.ToString();
}
public, private public znai da u tim osobinama jedne klase moi
pristupiti i iz neke druge klase. Private lanovima mogu pristupiti
samo iz one klase u kojoj sam ih definisao.

Property
public decimal Prosek
{
get
{
return decProsek;
}
set
{
decProsek = value;
}
}
Property se sastoji iz dva dela. Set deo koji se izvrava kada
elimo da dodelimo vrednost. U tom sluaju se vrednost koja se
dodeljuje prosleena sa vrednosu value. Get deo slui da se
proita vrednost propertija.
Nasleivanje Kada hou da napravim novu klasu koja treba da
preuzme sve osobine neke klase i da dopunim sa novim metodama i
osobinama to se radi nasleivanjem. Primer:
class Student:Osoba
{

Objekat kada smo napravili klasu treba da je i upotrebimo. Potrebno je da


napiemo sledee

Student stPrvi = new Student();


stPrvi.strIme = "ja";

prvim redom zapravo kaemo sledee:


(sa leve strane jednakosti)definiem promenljivu stPrvi i ona je tipa klase Student
(sa desne strane jednakosti) kreiraj novu istancu klase (kreiraj novi objekat klase)
Student.
U sledeem redu osobini strIme objekta stPrvi dodeljujem vrednost.
MessageBox upotreba MessageBox-a kada oekujem rezultat (dugme koje je
pritisnuto u njemu).
DialogResult odgovor = MessageBox.Show("Da li vidis
poruku?", "Pitanje", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (odgovor == DialogResult.Yes)
{
// ta treba uraditi ako je korinik pritisnuo Yes
}
Ono to treba primetiti da MessageBox.Show vraa rezultat tipa
DialogResult. Funkcija frm.ShowDialog() koju emo koristiti da bi
prikazali formu takoe vraa rezultat istog tipa DialogResult.

CheckBox, RadioButton poseduju osobinu Checked. CheckBox slui da se postavi


pitanje koje ima dva odgovora tano i netano. Recimo odsliili ste vojsku?.
RadioButton slui za to da ponudite meusobno iskljuujue opcije. Recimo hoete
da ponudite korisniku da izabere boju, ali bez mogunosti izbora dve odjednom.
Reenje je upotreba RadioButton-a.
Parse esta potreba koju imamo je da se upisani tekst pretvori u broj, datum
Najlaki nain da se to izvede je korienjem Parse metode. Na primer
int n=int.Parse("3");
string omoguuje nam lak rad sa tekstom. Ovo su primeri korienja
nekih metoda.
IndexOf pozicija prvog pojavljivanja u tekstu.
Remove -briem odreeni deo teskta.
Insert ubacuje tekst na odreeno mesto.
string prvi = "Draga mama meni je dobro";
prvi.Remove(prvi.IndexOf("Draga"),5);// nije sauvao promenu
prvi.Replace("je", "nije");// nije sauvao promenu
prvi = prvi.Insert(prvi.IndexOf("je"), "ni");// tek sada sam
stvarno promenio promenljivu prvi
DateTime, TimeSpan slue za rad sa vremenom i sa vremenskim
intervalom
DateTime dt = DateTime.Now;
dt=dt.AddDays(5);
dt=dt.AddMonths(2);

richTextBox1.AppendText(dt.ToLongDateString()); - ispisuje
se datum (nain ispisa zavisi od Regional Settings u Control Panel-u )
TimeSpan razlika = dt.Subtract(DateTime.Now);
richTextBox1.AppendText("\n" + razlika.Days.ToString());
try, catch jedan od problema koji mogu da nastanu u programu je
sledei. Korisnik usnese podatak koji niste predvideli. Recimo pravite
program za sabiranje, a korisnik ukuca slova umesto brojeva. Nain da
se prevazie problem je da se problematini deo programa stavi u try
blok. Program e pokuati da izvri program, ako se desi greka prei
e u catch
try
{
int.Parse("ta e sad?");
}
catch
{
MessageBox.Show("I dalje radim!");
}

PRIMERI
1) Na jednoj formi postoji tri TextBox-a. Prva dva slue za unos operanada, a trei za
ispis rezultata. Postaviemo dva RadioButtona (rbSaberi i rbOduzmi). Na kraju
potreban nam je i button. Kada se pritisne button potrebno je izvriti izvriti izabranu
operaciju.
Dodajmo novu klasu u projekat
class Operacije
{
public Operacije()
{
}
public decimal Operand1;//opisuje klasu pise se u okviru klase a ne u okviru
konstruktora
public decimal Operand2;
public decimal Zbir()
{
return Operand1 + Operand2;
}
public decimal Razlika()
{
return Operand1 - Operand2;
}
}
Kliknemo na button u formi1 i napiemo sledee
private void button1_Click(object sender, EventArgs e)
{
Operacije tmp = new Operacije();

try // pokusaj da uradis ovo ako se desila greska prekida izvrsavanje


programa, a ako je ispravno onda nastavlja sa izvrsavanjem bloka
{
tmp.Operand1 = decimal.Parse(textBox1.Text);
tmp.Operand2 = decimal.Parse(textBox2.Text);
if(rbsaberi.Checked) //da li je radio buton cekiran
textBox3.Text =tmp.Zbir().ToString();
else if (rboduzmi.Checked)
textBox3.Text=tmp.Razlika().ToString();
}
catch
{
MessageBox.Show("Niste uneli broj!");
}
}
2)Postoje dve forme: na prvoj imamo jedno dugme i jedan textbox, druga forma ima
textbox i dva dugmeta (sauvaj i odustani). Kada se pritisne dugme na prvoj formi
treba da se otvori druga forma. Tada se upie neto u textbox druge forme. Ako se
pritisne dugme sauvaj treba da se zatvori druga forma i da se prenese tekst sa druge
forme u textbox prve forme. Ako se pritisne dugme odustani samo se zatvara druga
forma.

Prvo to treba da uradimo kada dodamo i drugu formu u projekat je da definiemo


public promenljivu u njoj (da bi mogli da joj pristupimo iz forme1). To se radi desnim
klikom na ime aplikacije odakle se odabere Add Windows Form... .

public string strTekst;

Zatim napravimo procedure koje se izvravaju na klik korisnika na dugme


private void btnSacuvaj_Click(object sender, EventArgs e)
{
strTekst = textBox1.Text;
this.DialogResult = DialogResult.OK;
this.Close();
}
private void btnOdustani_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}

Na kraju, kod koji se nalazi u prvoj formi je sledei


private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
DialogResult rez=frm.ShowDialog();
if (rez == DialogResult.OK)
textBox1.Text=frm.strTekst;
}

3) Kada se startuje program pojavljuje se forma za logovanje (sadri


dva textbox-a i jedno dugme button1). Korisnik treba da unese
korisniko ime i lozinku. Ako je provera uspena treba otvoriti drugu
formu. Ako korisnik tri puta pogrei treba zabraniti dalji rad u
programu.
Treba primetiti da broja neuspelih pokuaja mora biti definisan van
button1_Click funkcije. U suprotnom bi se broja resetovao sa svakim
pozivom funkcije.
int indikator = 0;
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "proba" && textBox2.Text == "proba")
{
Form2 frm = new Form2();
frm.ShowDialog();
}
else
{
indikator++;
if (indikator == 3)
button1.Enabled = false;
}
}

1) PRINCIP RADA PROGRAMA KOJI PRISTUPA BAZI PODATAKA


DataSet
Zamislite da ste vlasnik vie prodavnica u jednom gradu. Problem se sastoji u
tome gde e te smetati robu koju nabavite od dobavljaa.
- Da li je reenje da pored svake prodavnice napravite magacin?
- Da li je reenje da napravite centralni magacin koji se nalazi van grada?
Naravno da je reenje da napravite magacin van grada, ali bilo bi loe kada bi se
moralo im nestane proizvoda na rafu u prodavnici ii po njega u glavni magacin. Dakle
optimalno reenje je da postoji centralni magacin, ali i da u okviru same prodavnice
napravimo priruni magacin gde emo drati dopunu za robu koja se najvie prodaje.
Sada da prebacimo ovaj primer u raunarski svet. Kada priamo o prirunom
magacinu, priamo zapravo o cash-u. U sluaju programa za rad sa bazom podataka
priamo o DataSource-u ili DataSet-u. DataSet je baza (magacin) u malom. U njemu
postoje tabele, konstreinti, relacije praktino sve to nam nudi i prava baza.
A zato onda da kupujemo i koristimo bazu? Nije cilj DataSet-a da zameni bazu.
Brzina i sigurnost podataka su daleko ispod prave baze. On se upotrebljava da iz baze
uzmemo deo podataka. Glavni zadatak DataSet-a je da pamti ta se dalje deava sa tim
podacima. Dakle DataSet moemo da pitamo sledee:
Koji su to novododati redovi?
Koji su to obrisani redovi?
Koji su to izbrisani redovi?
SqlDataAdapter - TableAdapter
Ali DataSet ne treba da zna nita o poreklu podataka koji su u njemu. O itanju
podataka iz baze, upisivanju izmena nazad u bazu brine se SqlDataAdapter (ili u okviru
DataSource-a TableAdapter).
Kako TableAdapter zna da uradi te operacije? Postoje SqlCommand objekti u
okviru njega: SelectCommand, InsertCommand, UpdateCommand i DeleteCommand.
Zapravo prilikom korienja TableAdaptera mi zapravo koristimo dve metode:
- Fill u pozadini koristi SelectCommand slui da deo podataka iz baze
prenesemo u DataSet
- Update u pozadini koristi InsertCommand, UpdateCommand i
DeleteCommand slui da izmene koje nastanu u DataSetu upie u bazu.

Na primer :
klijentiTableAdapter.Fill(this.videotekaDataSet1.klijenti);
- puni tabelu u DataSet-u
klijentiTableAdapter.Update(this.videotekaDataSet1.klijenti);
- Promene koje su nastale u tabeli DataSet-a upisuje u bazu

SqlCommand
Kada smo doli do SqlCommand objekata, da vidimo od ega se oni sastoje. (O
SqlCommand objektu je najbolje da itate kada shvatite ostale objekte)
Bitne osobine su:
CommandType mogue vrednosti CommandType.StoredProcedure i
CommandType.Text

CommandText u sluaju CommandType.StoredProcedure ovde treba


napisati ime store procedure koju treba izvriti. U sluaju
CommandType.Text treba napisati sql upit koji treba izvriti.
Naprimer
MojaKomanda.CommandType= CommandType.Text;
- ovaj red nisam morao napisati jer je to podrazumevana vrednost
MojaKomanda.CommandText=Delete from klijenti where klijent=3;
ili
MojaKomanda.CommandType= CommandType.StoredProcedure;
MojaKomanda.CommandText=ObrisiKlijenta;
- ime store procedure
Parameters ta se deava kada u CommandText-u imamo parametar
ili ako StoreProcedure koju elimo da pozovemo ima parametre? Na primer
napiemo:
MojaKomanda.CommandText=Delete from klijenti where
klijent=@klijentID;
U tom sluaju moramo definisati i parametar
myCommand.Parameters.Add ( "@klijentID", SqlDbType.Int);
da sam imao neku tekstualnu promenljivu napisao bih
myCommand.Parameters.Add ( "@PunoIme", SqlDbType.NVarChar,255);
Da bih dodelio vrednost odgovarajuem parametru treba da napiem
sledee:
myCommand.Parameters["@klijentID"].Value=1;
Postoji jo jedna stvar kod parametara. Postoji mogunost da
recimo store procedura ima i izlazne parametre. Da bi se to podesilo
postoji Direction osobina parametra. Primer je:

myCommand.Parameters["@klijentID"].Direction =
ParameterDirection.Output;
Connection SqlConnection objekat za koga je vezan ovaj komandni
objekat.
Na kraju ostaju metode:
myCommand.ExecuteNonQuery(); - izvravam komandu komandu ne
oekujem rezultat.
myCommand.ExecuteScalar(); - izvravam komandu koja vraa
rezultat. Recimo da sam napisao
MojaKomanda.CommandText=select count(*) from klijenti;
int brojklijenata= (int) myCommand.ExecuteScalar();
myCommand.ExecuteReader(); - neemo koristiti rezultat je
SqlDataReader objekat

SqlConnection
Ovo bi ve trebalo biti prilino jednostavan objekat. Sadri jednu vrlo bitnu
osobinu a to je ConnectionString. U ConnectionString-u se nalazi informacije potrebne
informacije za pristup sql serveru. SqlConnection sadri dve bitne metode:
- Open otvara konekciju ka bazi
- Close zatvara konekciju ka bazi
Treba primetiti sledee kada koristimo TableAdapter otvaranje i zatvaranje
konekcije se deava automatski, to nije sluaj sa SqlCommand. Da bi izvrili
SqlCommand operaciju konekcija mora biti otvorena.
ConnectionString se pamti u app.config fajlu. Obratite panju na name osobinu
Na primer:
<add
name="WindowsApplication1.Properties.Settings.Veleprodaja3ConnectionStr
ing"
Da bi programski pristupio vrednosti ovog stringa treba da
napiem sledee(primetite da posle Settings treba napisati Default)
WindowsApplication1.Properties.Settings.Default.Veleprodaja3Conne
ctionString
A ovako se pristupa ConnectionString-u u koliko je u pitanju web aplikacija,

a string se nalazi u web.config fajlu.


System.Configuration.ConfigurationManager.ConnectionStrings["webC
onnectionString"].ToString();

BindingSource
Pria se naalost ne zavrava ovde. Prethodni objekti nam slue da podatke iz
baze prebacimo u DataSet i da radimo nad podacima u bazi. Sa druge strane imamo
kontrole na fomi kao to su TextBox, CheckBox, ComboBox kao i kontrole koje slue za
prikaz tabelarnih podataka DataGrid i GridView. Izmedju ovih kontrola i DataSet-a
postoji dodatan objekat BindingSource. BindingSource ima vie funkcija
- definie koji je red trenutno selektovan (izvor podataka je obino niz redova).
Kada se menjaju podaci menjaju podaci, menjaju se u jednom redu. Kada se prikazuju
podaci u TextBox-u prikazuju se iz jednog reda (koji je to red definie BindingSource).
Npr. Na jednoj formi imate ComboBox i TextBox-ove. ta je potrebno uraditi da bi kada
se promeni selektovana osoba u ComboBox-u dodatne informacije o toj osobi pojavile u
TextBox-ovima. Potrebno je da sve imaju zajedniki BindingSource. Uz pomo

ComboBox-a se moe promeniti trenutno selektovani red, time e se promeniti selekcija


BindingSource-a, a time e se promeniti i sadraj TextBox-ova.
Metode koje se koriste u BindingSource-u
- KupciBindingSource.EndEdit(); - prihvataju se sve promene
koje su nastale na selektovanom redu
KupciBindingSource.CancelEdit(); - odustaje se od svih
promena koje su nastale na selektovanom redu
- KupciBindingSource.AddNew(); - dodaje se novi red u tabelu.
Novododati red je postao automatski selektovan
- KupciBindingSource.RemoveAt(pozicija); - brie se
odgovarajui red i DataSet-a
KupciBindingSource.RemoveAt(KupciBindingSource.Position);obrisau iz DataSet-a red koji je trenutno selektovan
Bitno je jo da znate kako da doete do reda koji je
trenutno selektovan.
DataRowView dr =
(DataRowView)kupciBindingSource.CurrencyManager.Current;
Dakle koristim BindingSource da bih dosao do
CurrencyManager-a, a iz njega preko Current osobine do neega
to je tipa DataRowView. (odnos DataRow-a i DataRowView-a je
isti kao i izmeu jednog reda u tabeli i jednog reda u pogledu
na tu tabelu)
Kada smo doli do selektovanog reda ostaje da doemo do
vrednosti neke kolone
(int)dr["kupacid"];
-

SqlDataReader
Navodim ga samo da bi pria o objektima bila zaokruena ali ne i zbog toga to
u navesti primer korienja. Postoje neki sluajevi kada nam nije potrebno keiranje
podataka. Najbolji primer za to je kada treba da prikaem neki izvetaj, statistike
podatke U tim sluajevima ne oekuje se da korisnik izmeni podatke ve samo da ih
pogleda. Na primer u formi iznajmljivanja treba ponuditi da se u ComboBoxu pokae
spisak kaseta koje se iznajmljuju, ali se ne oekuje da e korisnik u ovoj formi moi da
doda novu kasetu, ili izmeni ime postojee, za to smo napravili formu kasete. Dakle
ponuda kasete su kandidat za to da ne budu keirane nego da se podaci direktno popune
iz baze. Za to slui SqlDataReader.
NAPOMENA Da bi koristili navedene objekte morate dodati sledee
namespace-ove na poetku fajla (tamo gde vidite using System; i sl.)
Za DataSet treba da postoji
using System.Data;
za SqlDataAdapter, SqlCommand, SqlConnection, SqlDataReader
using System.Data.SqlClient;

PRIMERI:
Ovo su primeri programa koji se prave programiranjem a ne korienjem
dizajnera.
1) pravljenje sqldataadaptera i dataseta
SqlConnection con=new SqlConnection(

WindowsApplication1.Properties.Settings.Default.Veleprodaja3ConnectionS
tring);
SqlDataAdapter dap = new SqlDataAdapter("select * from
kupci", con); - praktino ovo pravi samo SelectCommand u okviru
SqlDataAdaptera
DataSet ds = new DataSet(); - pravim prazan dataset
dap.Fill(ds, "kupci"); - izvriu dataadapter I rezultat
smestiti u dataset u tabelu koju u nazvati kupci
// vrim programsko setovanje ComboBox1-a
comboBox1.DataSource = ds;
comboBox1.DisplayMember = "kupci.ImePrezime";
comboBox1.ValueMember = "kupci.kupacID";
2) Izvravanje komande koja brie red bez parametra
string strCmd = String.Format("DELETE FROM kontakti WHERE id = {0}",
lbxKupci.SelectedValue);
SqlConnection sqlConn = new SqlConnection(
Aplikacija.Properties.Settings.Default.kontaktiConnectionString);
SqlCommand cmd = new SqlCommand(strCmd, sqlConn);
sqlConn.Open();
cmd.ExecuteNonQuery ();
sqlConn.Close();
3) Izvravanje komande koja brie red sa parametrom
string strCmd = "SELECT slika FROM kontakti WHERE id =@id";
SqlConnection sqlConn = new SqlConnection(
Aplikacija.Properties.Settings.Default.kontaktiConnectionString);
cmd.Parameters.Add("@id", SqlDbType.Int).Value =
(int)lbxKupci.SelectedValue ;
SqlCommand cmd = new SqlCommand(strCmd, sqlConn);
sqlConn.Open();
cmd.ExecuteNonQuery();
sqlConn.Close();
4) Izvravanje komande koja vraa jednu vrednost broj kontakata u
tabeli.
string strCmd = String.Format("SELECT count(*) FROM kontakti");
SqlConnection sqlConn = new SqlConnection(
Aplikacija.Properties.Settings.Default.kontaktiConnectionString);
SqlCommand cmd = new SqlCommand(strCmd, sqlConn);
sqlConn.Open();
int broj = (int)cmd.ExecuteScalar();
sqlConn.Close();