BHGridCtrl- open source


BHGridCtrl

BHGridCtlr zadnja verzija Februar 2006

C++ Grid kontrola razvijana isključivo iz hobija u slobodno vrijeme. Na blogu je otvorena stranica na kojoj su sumirani članci koje sam ranije pisao, kao i članci koje ću objaviti, vezano za ovu kontrolu.U slučaju da imate vremena na pretek ili veliku želju da programirate u C++ ovakvu kontrolu, slobodno me kontaktiraje, zaista bi bilo lijepo kada bi se ova kontrola nastavila razvijati.

Više o projektu na stranici Projekti->BHGridCtrl.

Advertisement

Lokalizacija .NET aplikacija


Uvod

Lokalizacija je proces koji se koristi pri razvoju aplikacija koje podržavaju više od jednog jezičkog ili geografskog pojma. Usavršavanjem razvojnih alata, a posebno microsoftove .NET platforme, lokalizacija aplikacija nije nikada bila jednostavnija i brža. Prethodne platforme imale su kompleksan sistem lokalizacije koje su se implementirale na razne načine i izvan jednog IDE (integrisanog razvojnog okruženja). Lokalizirati aplikaciju na .NET platformi danas predstavlja vrlo jednostavan i intuitivan posao, jer sve što nam je potrebno da lokaliziramo aplikaciju na jedan ili više jezika i pisama nalazi se ugrađeno u .NET platformi, sa raznim dizajnerskim alatima koje posjeduje Visual Studio. Način lokalizacije u .NET definisan je iznad .NET programskih jezika C# i VB.NET tako da je ovaj proces gotovo nezavisan od programskog jezika.

Da bi mogli izvršiti lokalizaciju jedne aplikacije potrebno je upoznati sljedeće prostore naziva:

1. System.Globalization. Ovaj prostor čine klase koje definišu informacije o kulturama (državama), koje uključuju jezike, zemlje i regione, kalendare, formate datuma, monetu, brojeve, stringove za sortiranje… Od svih klasa koje čine ovaj prostor CultureInfo je klasa koju najviše koristimo.

2. System.Resources. Ovaj prostor čine klase s kojim se formira resurs datoteke raznih jezika i kultura. Klasu s kojom se veći dio posla obavlja je ResourceManager. Ovom klasom se obezbjeđuje pristup resursima kontrola koje su pohranjene u glavnom asembliju (dll-u).

Prilikom lokalizacije unutar Visual studia svaka forma posjeduje datoteke resursa u kojoj su odvojene jezičke implementacije teksta. Kada se aplikacija kompajlira formiraju se satelitski dll-ovi, smješteni u foldere koji dobijaju nazive oznaka jezika, kao što je prikazano na sljedećoj slici.

clip_image002

Svaki folder sadrži datoteku čiji se naziv sastoji od tri pojma: Naziva glavnog dll ili aplikacije, resource riječi te ekstenzije, npr. ImeAplikacije.resource.dll . Kada se aplikacija počne učitavati u memoriju računara na osnovu parametara CultureInfo klase učitava se korespodentni satelitski dll, a GUI se ispisuje na odabranom jeziku.

clip_image004

Primjer aplikacije

 

Da bi izvršili lokalizaciju potrebno je formirati testnu aplikaciju, te implementirati svu funkcionalnost koja je potrebna, te onda pristupiti lokalizaciji. Za ovaj primjer formirana .NET aplikacija koja posjeduje jednu formu kao na sljedećoj slici.

clip_image006

Glavna forma sadrži Tab kontrolu koja posjeduje 3 stranice.

  1. Prva stranica „Opće kontrole“ sadrži nekoliko osnovnih kontrola te kombo box za promjenu jezika.
  2. Druga stranica „Pismo“ sadrži konverziju teksta sa latinice na ćirilicu i obrnuto
  3. Treća stranica „Kalendar“ sadrži konverziju datuma sa gregorijanskog kalendara u kalendar po Hidžri.

Testna aplikacija pokazuje razne slučajeve lokalizacije, i korištenje gore pomenutih klasa.

Kako aplikacija radi….

Kada pokrenemo aplikaciju prvi put učitava se Osnovni jezik „Bosanski“. U prvoj stranici Tab kontrole imamo jednu listBox kontrolu i način na koji možemo lokalizirati stavke listbox kontrole, manipulirajući sa glavnom resurs datotekom aplikacije. Također imamo datagridview kontrolu i način na koji lokaliziramo nazive kolona u njoj. Kada kliknemo na dugme Dodaj u listbox kontrolu dobijamo novu stavku zavisno na kojoj se trenutno lokalizaciji aplikacija nalazi.

U aplikaciji su implementirane 3 lokalizacije: Engleski jezik, Hrvatski Jezik, Srpski jezik. Kao osnovni jezik prikazan je Bosanski. Kada izaberemojezik iz komboboxa, aplikacije se restartuje a zadnji odabrani jezik učita se u aplikaciju. Moguće je promijeniti jezik u aplikaciji i bez restartovanja aplikacije, ali takav način bi izgubio jednostavnost ovog članka.

Druga stranica Tab kontrole sadrži konvertore između latinice i ćirilice. Metoda koja konvertuje latinicu u ćirilicu prenešena je sa www.elitesecuruty.org, a modificirana je kao proširena string metoda. Metoda koja konvertuje ćirilicu u latinici analogno je implementirana.

Upisivanjem teksta u editkontrolu i aktivacijom dugmeta na desnoj edit kontroli se pojavljuje konvertovani tekst.

clip_image008

Treća stranica Tab kontrole prikazuje na koji način pretvaramo gregorijanski kalendar u kalendar po Hidžri..NET framework posjeduje posebnu klasu System.Globalization.HijriCalendar s kojim prikazujemo datum po Hidžri. U svrhu konvertovanja datuma u datum po Hidžri potrebno je izvršiti dodatna formatiranja, jer se imena dana i mjeseci dobijaju na arapskom. Naravno potrebno je takva imana prevesti na latinične nazive. U ovoj implementaciji definisana je također proširena metoda DateTime klase pomoću koje se vrlo jednostavno pretvara datum po Hidžri.

image

Implementacija aplikacije

U prethodnom dijelu opisana je sama aplikacija na koji način radi i što je sve implementirano. Ovim poglavljem ćemo ukratko opisati na koji je način aplikacija implementirana.

  1. Formirati Novi projekat u VS, New Windows Forms Application
  2. Formirati kontrole kao što su prikazane
  3. Formirati Utility Klasu u kojoj su implementirane proširene metode
  4. Lokalizirati glavnu formu
  5. Lokalizirati glavnu resurs datoteku aplikacije
Lokalizacija aplikacije

 

.NET tehnologija lokalizaciju definiše sa nivoa projekta do nivoa jedna forme. Ovaj način lokalizacije obezbjeđuje fleksibilnost u samom procesu. Lokalizacijom na nivou projekta omogućeno je definisanje različitih verzija Resource datoteke.

clip_image010

U datoteku Resource.resx postavljena je varijabla listBoxStavka, koja sadrži naziv stavke u listbox kontroli. Resurs datoteka je iskopirana i preimenovana shodno sljedećim skraćenicama:

· en-US – Engleski US

· hr-HR – Hrvatski

· sr-Cyrl-CS – Srpski

Na osnovu toga formirane su datoteke resources.(jezik).resx, koje su prikazane na gornjoj slici. Kada su datoteke formirane te listBoxStavka prevedena na korespodentni jezik, sada u aplikaciji pristupamo datim strignovima preko ResourceManager-a:

clip_image012

Lokalizacija forme počinje kada osobinu Localizable postavimona true, te Language postavimo na željeni jezik:

clip_image014

Nakon toga dizajner formira resurs datoteku unutar forme. Isti postupak ponavljamo za onoliko jezika koliko je potrebno. Kada su resurs datoteke formirane potrebno je stringove iz Form1.resx, kopirati u formirane datoteke te lokalizirati. Ovim procesom je izvršena lokalizacija.

Postavljanje jezika u aplikaciji

Postavljanje jezika u aplikaciji vršimo sljedećim kodom koji prikazuje lokalizaciju na engleski:

clip_image016

Nakon izvršenja ovog koda potrebno je aplikaciju restartovati. Gornji kod se postavlja prije inicijalizacije glavne forme u aplikaciji.

Konverzija datuma u datum po Hidžri

Obzirom da .NET posjeduje lokalizaciju zemalja kod kojih se datum računa po Hidžri, potrebno je koristeci jednu od dotičnih lokalizacija, standardni zapadni datum konvertovati u datum po Hidžri. Ovdje je problem kada želimo da formatiramo mjesec i dan po imenu, pri čemu dobijamo nazive na arapskom pismu. Proširena metoda konverzije datuma sadrži također nazive mjeseci i dana u sedmici napisane onako kako se piše i izgovara na postoru Bosne i Hercegovine .

clip_image018

Kompletan source kod možete skinuti sa ovog linka.

Prenos tabele kao argument storne procedure


Na koji način prenijeti tabelu sa podacima u stornu proceduru kao argument?!

Na ovo pitanje i nije baš lako odgovoriti jer se tabela konvencionalno ne može prenijeti kao argument u stornu proceduru. U tom smislu rješenja koja se nude su različita, i kreću se od toga da se tabela eksportuje u tekst, koji je odvojen karakterom za odvajanje, pa se onda kao varchar prenese u stornu proceduru. Poslije toga je potrebno taj isti text vratiti u privremenu tabelu te onda je koristiti. Ovaj postupak pored toga što je potrebno implementirati logiku vraćanja teksta u tabelu, ima mane limitiranja broja karaktera.

SQL Server 2005 posjeduje XML  data tip, koji pored mnogih korisnih prednosti ima mogućnost da se definiše kao argument u stornoj proceduri. Na ovaj način moguće je tabelu izvesti u xml i na taj način prenijeti podatke. Obzirom da je manipulacija sa xml-om podržana u SQL koristeći se standardnim operacijama i naredbama.

Kao ilustraciju navedenog problema prikazaćemo mali tutorijal na koji način to možemo postići. U biti formiraćemo .NET aplikaciju u VS 2008, formirati Typed DataSet u kojoj ćemo mapirati jednu tabelu koju treba prenijeti u stornu proceduru, te mapirati stornu proceduru koju smo formirali na sql serveru koja prima XML tip i vraća tabelu koja je prenešena XML u SP.

1. Otvorimo VS 2008, i formirajmo .NET aplikaciju kao na slici:

clip_image002

2. Nakon formiranja aplikacije formirajmo TypedDataSet i nazovimo ga DataSet1.xsd

clip_image004

Napomena: Kada formirate DatSet, potrebno je obrisati NameSpace: http://tempuri.org/DataSet2.xsd

image

3. U DataSet1 formirajmo DataTable i nazovimo je „Tabela“.

Napomena: Ako pratite tutorijal vrlo je važno da se imenuje DataSet i DataTable istim imenom kao i ovdje, jer SQL kod koji ćemo kasnije formiati bazira se na ovim imenima.

4. U DataSet1 formiramo tabelu bez Adaptera kao na sljedećoj slici:

clip_image006

clip_image008

5. Kada smo formirali tabelu i definisali tipove podataka koje treba da sadrži, sad smo u mogućnosti da napravimo stornu proceduru koja će kao argument prihvatati našu tabelu.

6. Otvorimo NorthWind bazu preko ServerExplorera, u koliko nemate NorthWind bazu uzmite bilo koju ili je skinite sa ms stranice. Formirajne novu stornu proceduru kao na slici:

clip_image010

7. Storna procedura izgleda kao na sljedećoj slici

clip_image012

U biti procedura sadrži kod za formiranje privremene tabele, te ekstraktovanje podataka iz XML-a. Kod ekstrakta podataka potrebno je paziti na nazive DataSeta, naziva tabele, kao i naziva kolona kao što je prikazano.

8. Odabirom “Save” dugmeta zapisujemo proceduru na server. U DataSet-u sada je potrebno proceduru mapirati da bi je mogli prikazati u našoj testnoj aplikaciji.

9. Formirajmo TableAdapter

clip_image014

10. Odaberimo Postojeću proceduru na serveru

clip_image016

11. Odaberimo proceduru koju smo formirali nedavno

clip_image018

12. Na kraju u našem DataSetu imamo dvije tabele. Jedna offline (koju ćemo prenijeti u SP) i druga tabela koja je mapirala našu proceduru.

13. Otvorimo Form1.cs i odvucimo i spustimo naše formirane tabele kao na slici:

clip_image020

14. Implementirajmo Form_Load događaj, te formirajmo dugme “Napuni tabelu iz SP” preko kojeg ćemo pozvati Stornu proceduru.

clip_image022

Napomena: Na gornjoj slici smo formirali metodu za učitavanje podataka u tabelu. Na isti način smo mogli koristiti bilo koju tabelu sa servera, stim što bi je tada napunili preko tableAdaptera iz baze podataka.

15. Implementacija događaja za dugme “Napuni tabelu iz SP” ima sljedeću formu:

clip_image024

Na ovaj način smo završli tutorijal. Potrebno ga je testirati. U koliko je tutorijal pravilno sproveden nakon pokretanja aplikacije, te klikom na dugme „Napuni tabelu iz SP“ dobijamo sljedeći izgled.

clip_image026

U biti formirali smo tabelu, napunili je podacima, prosljedili je u SP, a SP nam je vratila tu istu tabelu.

Izvorni kod sa implementacijom storne procedure može se skinuti sa ovog linka.

yield naredba u C#


yield je ključna riječ (naredba) koja se pojavila izlaskom C# 2.0 i Visual Studio 2005. Oficijelna (MSDN) definicija kaže da je ovo ključna riječ koja upućuje informaciju kompajleru da metoda u kojoj se pojavljuje yield posjeduje dio koda za iteraciju. Kada kompajler naiđe na ovu riječ on formira klasu u koju implementira logiku i način na koji će se yield izvršavati. Ovo znači da yield nije osobina .NET Frameworka, nego čisto C# programskog jezika. U bloku za iteraciju yield se koristi zajedno sa return za vraćanje vrijednosti u objekat enumeracije. yield se može koristiti i sa break da bi se prekinula iteracija. yield koristi tzv. lazy evaluaciju, da se evaluacija odigrava u vrijeme izvršavanja ovog koda. Pogledajmo sljedeći dio koda:

static IEnumerable<int> F()
{  return 1;
   return 2; // Nikad se neće izvršiti
}

U ovom kodu imamo naredbu return jednu iza druge. Naravno druga naredba neće se nikad izvršiti, odnosno metoda F() uvijek vraća vrijednost 1. Pogledajmo gornji kod kada koristimo yield:

static IEnumerable<int> F()
{
  yield return 1;
  yield return 2; // Može biti izvršeno
}

Za razliku od prethodnog primjera, yield zajedno sa return naredbom će vratiti vrijednost 2 kada se ova metoda poziva kroz foreach petlju.

static IEnumerable<int> F()
foreach(var item in F())
 Console.WriteLine(item.ToString());

Kada izvršimo ovaj dio koda izlaz na konzoli je sljedeći:

Izlaz:
1
2

Potrebno je imati na umu određena ograničenja prilikom korištenja ove naredbe

  • Ako yield koristimo izvan bloka metoda, operatora kompajler će prijaviti grešku
  • yield se ne može koristiti unutar anonimne funkcije
  • yield ne smijemo također koristiti u bloku finally
  • yield return ne smijemo koristiti kada try posjeduje catch u bilo kojoj varijanti

Primjena yield naredbe u rješavanju problema

Sa yield naredbom vrlo elegantno možemo rješavati određene probleme pogotovi kada je potrebno da se određenom iteracijom dobije rezultat. Jedan od problema koji se vrlo jednostavno rješava je prebrojavanje prostih brojeva.

Prebrojavanje prostih brojeva

U jednom od postova implementirana je metoda za provjeravanje prostih brojeva, bez korištenja yield naredbe, kada se govorilo od ParallelFx. U narednom tekstu data je implementacija prebrojavanja prostih brojeva manji od n uz upotrebu yield naredbe.

//Prebrojavanje prostih brojeva manji od n
public static IEnumerable<int> VratiProsteBrojeve (int n)
{
  yield return 2;
  yield return 3;
  for (int i = 4; i < n; i++)
  {
   bool bprostBroj = true;
   for (int j = 2; j*j <= i; j++)
    if (i % j == 0)
     bprostBroj = false;
  if(bprostBroj)
   yield return i;
  }
static void Main(string[] args)
{
   //Prebrojavanje prostih brojeva manji od n
   foreach (var item in VratiProsteBrojeve (10))
     Console.WriteLine(item.ToString());
   //Press any key to continue...
   Console.Read();
}

Obzirom da posjedujemo metodu za prebrojavanje prostih brojeva otvaraju nam se bezbroj mogućnosti da kroz LINQ također vršimo određene upite. Npr. Želimo da izračunamo sumu prostih brojeva manjih od n. Ništa lakše:

var suma = Program. VratiProsteBrojeve (n).Sum();

Sada naš izlaz na konzolu izgleda kao na sljedećoj slici.

Ako želimo da izračunamo sumu kvadrata prostih brojeva manji od n imamo sljedeći primjer:

var sumaKvadrata = (from p in VratiProsteBrojeve (n) select p * p).Sum();

Rastavljanje na proste faktore

Svi smo učili iz matematike u Osnovnoj školi rastavljanje broja na proste faktore. U ovom primjeru ćemo vidjeti na koji način koristimo yield naredbu prilikom rješavanja problema koji zahtjevaju korištenje rekurzije. Uradimo prvo pješice jedan primjer čisto da se podsjetimo šta to znači. Npr. rastavi na proste faktore broj 10.10=2*5, jer su 2 i 5 prosti brojevi.Potrebno je sada implementirati algoritam za rastavljanje broja na proste faktore. U narednom primjeru prikazana je metoda za foktoriziranje broja:

//Rastavljanje broja n na proste faktore n=n1*n2*n3*...nn; ni-prosti brojevi
public static IEnumerable<string> Foktoriziraj(string izraz, int n)
{
   //Ako je 1 vrati izraz
   if (n == 1)
     yield return izraz;
   else
    {
     //Prolazimo sve brojeve manje od n
     for (int i = 2; i <= n; i++)
       {
         //Ako je n djeljiv sa i
         if ((n % i) == 0)
          {
            int q = n / i;
            //Zapišimo u izraz broj i
            if (!izraz.EndsWith("= ")) izraz += " * ";
               izraz += i.ToString();
            //Sada q postaje n i primjenjujemo isti postupak sve dok ne postane 1
             foreach (string podizraz in Foktoriziraj(izraz, q))
               yield return podizraz;
             yield break;
           }
        }
     }
}

Ako želimo da broj 100 rastavimo na proste faktore pozovimo gornju metodu u sljedećoj formi.

Console.WriteLine(Foktoriziraj("100 = ", 100).SingleOrDefault());

yieldoutput001

U koliko želimo rastaviti na proste faktore prvih 10 prirodnih brojeva potrebno je:

for (int i = 1; i < 10; i++ )
   Console.WriteLine(Foktoriziraj(i.ToString() + " = ", i).SingleOrDefault());

Rezultat je dan na sljedećoj slici:

yieldoutput002

Reference:

  1. www.msdn.com
  2. The C# Programming Language 3th edition, Anders Hejlsberg
  3. http://startbigthinksmall.wordpress.com/2008/06/09/behind-the-scenes-of-the-c-yield-keyword/
  4. http://www.codeproject.com/KB/cs/IEnumerableAndYield.aspx