HyperLink
Bejelentkezés
E-mail: 
Jelszó: 





Skip Navigation Links
 

Adatkapcsolat tetszőleges kontrolokhoz, szinkronizálással


Példaprogram letöltése

8442 bájt

Ha az adatbázisaink tábláiból nem csak lekérdezni szeretnénk adatokat, hanem azokat fel is kellene tölteni és ehhez felhasználói beavatkozás is szükséges, akkor biztosítanunk kell, hogy különféle kontrolokhoz (DataGrid, TextBox, DateTimePicker, stb.) hozzá kell kötnünk az adattáblánk megfelelő oszlopait, hogy ezeken keresztül a felhasználó megadhassa a szükséges adatokat. Biztosítanunk kell az adatok szinkronizációját is. Vagyis, ha egy DataGrid-ben egy másik sorra lép a felhasználó, akkor célszerű, ha a többi adatmegjelenítő kontrol is ennek a sornak az adatait mutatja. További megoldandó feladat az is, hogy biztosítsuk az adatok egyedi formázását úgy, hogy azok továbbra is szerkeszthetők maradjanak. E cikkben e feladatok megvalósításának járunk utána.

Az adatok kontrolokhoz való kötését a Binding osztály valósítja meg elsősorban. Mielőtt megismerkednénk ezzel az osztállyal, előtte hozzunk létre egy adathalmazt, melyet felhasználhatunk.
Ehhez egy DataTable osztályt készítünk, melyben létrehozunk egy olyan táblát, mely két oszlopot tartalmaz. Az egyikben egy dátum típus, míg a másikban egy Int32 típus kap helyet.
      DataTable dt = new DataTable("Table01");
      dt.Columns.Add("Date", typeof(DateTime));
      dt.Columns.Add("Value", typeof(Int32));
Következzen az adat sorok létrehozása, melyhez egy új DataRow osztály példányát hozzuk létre a DataTable NewRow függvényét meghívva. Egy ciklus segítségével több adatsort is generálunk a példánkhoz.
      DataRow dr;
      for (int i=0; i<100; i++)
      {
        dr = dt.NewRow();
        dr[0] = DateTime.Now.AddDays(i);
        dr[1] = r.Next(Int32.MaxValue);
        dt.Rows.Add(dr);
      }
Végül az így elkészített adattáblát egy DataSet osztályban tároljuk.
      ds = new DataSet();
      ds.Tables.Add(dt);
Nézzük most miként köthetjük különféle kontrolokhoz a létrehozott adatokat. Minden olyan osztály rendelkezik DataBindings property-vel, ami ControlBindingsCollection osztály típusú, mely a Control osztályból származik. A DataBindings property-n keresztül tehát elérhetünk egy olyan kollekciót, mely tartalmazza a már létrehozott adatkapcsolatokat, illetve segít bennünket új kapcsolat létrehozásban is. Ez utóbbihoz az Add függvény nyújt segítséget, melynek két változata is van:
Add
Osztály: System.Windows.Forms.ControlBindingsCollection
public Binding Add(
string propertyName,
object dataSource,
string dataMember
);
Új adatkapcsolat létrehozását valósíthatjuk meg az Add függvény segítségével.
Paraméterek
string propertyName
A propertyName paraméterben kell megadnunk annak a property-nek a nevét, melyhez kötni szeretnénk az adatokat.
object dataSource
A dataSource paraméter adja meg az adatforrást.
string dataMember
A dataMember a dataSource adatforráson belül írja le annak az adathalmaznak a nevét, melyet a kontrol adott property-éhez szeretnénk kötni.
Visszatérési érték
Visszatérési értékként kapunk egy Binding osztály példányát, mely a létrejött kapcsolatot írja le.
Add
Osztály: System.Windows.Forms.ControlBindingsCollection
public new void Add(
Binding binding
);
Új adatkapcsolat létrehozását valósíthatjuk meg az Add függvény segítségével.
Paraméterek
Binding binding
Az adatkapcsolat leírását egy Binding osztály létrehozott példányában kell megadnunk, melyet a binding paraméterben adunk át.
Létrehoztuk tehát a Table01 nevű adattáblát és ezt szeretnénk a DataGrid-hez kötni. Ekkor az Add függvény első paraméterében a DataSource property nevét adjuk meg, mivel a DataGrid kontrolhoz e property-n keresztül köthető adat. A második paraméter az adatforrás lesz, mely a DataSet létrehozott példányát takarja. A harmadik paraméter az adatforráson belüli tábla lesz, mely Table01 néven került ott eltárolásra, mivel az egész adattáblát szeretnénk viszontlátni a DataGrid-ben.
      dataGrid1.DataBindings.Add("DataSource", ds, "Table01");
Kössük most a Table01 tábla Value nevű oszlopának adatait egy Label kontrolhoz. Ekkor az első paraméter a Text property neve lesz, mivel a Label kontrolnál ezen keresztül jeleníthetünk meg adatokat. A harmadik paraméter annyiban módosul, hogy most a Table01 tábla Value oszlopára kell hivatkoznunk. Nem is tehetnénk meg, hogy a Label-hez egy egész adattáblát rendelünk.
      label2.DataBindings.Add("Text", ds, "Table01.Value");
Az adattábla másik oszlopa a Date nevű hasonlóan kerül hozzákötésre egy DateTimePicker kontrol Value nevű property-jéhez.
      dateTimePicker1.DataBindings.Add("Value", ds, "Table01.Date");
Ha most elindítanánk a programot, akkor a lényeg már működne: minden kontrolban megjelenne az aktuális adat. A gond az lenne, ha változtatjuk a DataGrid-ben az aktuális sort, akkor a többi kontrolban nem ennek az új sornak az adatai jelennének meg. Hogy szinkronizáljuk ennek működését, az alábbiakat kell tennünk. Kell először is egy esemény, mely akkor jön létre, ha a DataGrid aktuális sora esetlegesen megváltozik. Ehhez a CurrentCellChanged eseményt használjuk fel. Itt azt kell elérnünk, hogy a többi kontrol is az új értékeket mutassa. Mivel ezt nem végezhetjük el manuálisan, így más megoldást kell keresnünk. Szerencsére van egy olyan osztály is, mely az adatösszekötés vezérlését végzi. Ez a BindingContext osztály, mely egy kollekcióban tartja az összes adatkötést. Minden elemnek van egy Position property-je, melyen keresztül megtudhatjuk, hogy egy adott összekötésnek hányadik sora az aktuális. A Position property-n keresztül nem csak lekérdezhetjük ezt az információt, de módosíthatjuk is.
Ha tehát a DataGrid-ben másik sorra áll a felhasználó, akkor nincs más teendőnk, mint a Position property értékét megváltoztatnunk, méghozzá az alapján, hogy DataGrid-nek hányadik sora az aktuálisan kijelölt.
    private void dataGrid1_CurrentCellChanged(object sender, System.EventArgs e)
    {
      this.BindingContext[ds, "Table01"].Position=dataGrid1.CurrentCell.RowNumber;
    }
A BindingContext osztályban van egy esemény is PositionChanged névvel, mely akkor jön létre, ha a Position property változik. További szinkronizációkhoz jól használható ez az esemény.
this.BindingContext[ds, "Table01"].PositionChanged+=new EventHandler(PositionChanged);
Ha létrehozunk ehhez egy eseménykezelőt, akkor a sender paraméterében egy BindingManagerBase osztályt kapunk, melyet tetszés szerint felhasználhatunk.
    private void PositionChanged(object sender, EventArgs e)
    {
      BindingManagerBase bmb = sender as BindingManagerBase;
      label4.Text=bmb.Position.ToString();
    }
A továbbiakban nézzük, miként valósíthatunk meg speciális formátumú adatmegjelenítést és adatbevitelt. Hogy mikor is lehet szükségünk ilyenre, arra nézzük az alábbi példát: ha az adattáblában adott egy olyan számokat tartalmazó mező, melyben pénz értékeket tárolunk, akkor az adat megjelenítésénél szebb megoldás lenne az „1450” helyett az „1450 Ft” felirat megjelenítése az adott kontrolban. Ha az adat szerkeszthető is, például TextBox-hoz kötöttük, akkor viszont az is meg kell oldanunk, hogy ha a felhasználó begépeli a „254 Ft” szöveget, akkor ez értelmezhető legyen és a beírt szövegből a 254, mint szám az adattáblánk megfelelő helyére kerüljön.
Természetesen ilyen feladat nem csak pénzösszegnél fordulhat elő, hanem bármilyen más, akár egyedi formázásnál is.
Két feladat adott tehát: az egyik mely az adattábla adatát a megfelelő formára konvertálja és egy másik, mely a felhasználó által beírt egyedi formátumot visszaalakítja az adattáblában tárolt adat formájára.
A mellékelt példában ennek bemutatására feltettünk a Form-ra egy TextBox-ot, melyhez a Table01 Value nevű, Int32 típusú adatát szeretnénk kötni. Az egyedi formázást úgy valósítjuk meg, hogy a megjelenítendő adat elé egy „tc: ” feliratot helyezünk. Ennek értelme nincs, de jól szemlélteti a fenti probléma megoldását. Ettől kezdve tehát a Value oszlop adatai úgy jelennek meg a TextBox-ban, hogy minden szám elé a „tc: ” felirat kerül. Ha a felhasználó változtat az adaton, akkor ott is elfogadott a „tc: ” előtag, melyet nyilván vissza kell alakítanunk az adattároláshoz az eredeti formára.
E két feladat elvégzéséhez a Binding osztály két eseményt tart fenn.
Format
Osztály: System.Windows.Forms.Binding
public event ConvertEventHandler Format;
A Binding osztály Format eseménye akkor jön létre, ha a felhasználó számára szükséges adatot meg kell jeleníteni. Ekkor az adaton egyedi formázást végezhetünk el.
Parse
Osztály: System.Windows.Forms.Binding
public event ConvertEventHandler Parse;
A Binding osztály Parse eseménye akkor jön létre, ha a felhasználó által megadott adatot kell konvertálni az adat tárolásához szükséges formára. Ekkor a Format eseménynél elvégzett konverziót kell visszafelé elvégeznünk, hogy az eredeti formátum jöjjön létre.
Hozzunk hát létre egy új adatkapcsolatot a TextBox számára, melyben felhasználjuk e két eseményt.
      Binding b = new Binding("Text", ds, "Table01.Value");
      b.Format += new ConvertEventHandler(BindingFormat);
      b.Parse += new ConvertEventHandler(BindingParse);
      textBox1.DataBindings.Add(b);
A Format esemény kezelőjénél első lépésben azt kell ellenőriznünk, hogy a kapott adatot, ha sztringgé konvertáljuk, az megfelelő lesz-e az alkalmazásunk számára. Ehhez a paraméterként kapott ConvertEventArgs DesiredType-ét kell ellenőriznünk. Ezt követően a Value property-ből kiolvasott aktuális érték elé a „tc: ” előtagot illesztjük és máris készen van a szükséges formázás: az adat megjelenhet a felhasználó számára.
    private void BindingFormat(object sender, ConvertEventArgs cevent)
    {
      if (cevent.DesiredType == typeof(string))
      {
        Int32 i = Convert.ToInt32(cevent.Value);
        cevent.Value = "tc: " + i.ToString();
      }
    }
Amikor a Parse esemény fut le, akkor a felhasználó változtatott a kontrolhoz kötött adaton, így nekünk vissza kell konvertálni az adatot annak tárolási formájára. Adott tehát most egy sztring, mely „tc: ” előtaggal kezdődik, melyet egy szám követ. Ahhoz, hogy a számot megkaphassuk csak törölnünk kell az előtagot, majd a sztringet számmá alakítani.
    private void BindingParse(object sender, ConvertEventArgs cevent)
    {
      if (cevent.DesiredType == typeof(Int32))
      {
        String s = Convert.ToString(cevent.Value);
        cevent.Value = Convert.ToInt32(s.Remove(0, 4));
      }
    }

Könyv
Ez a cikk megtalálható ebben a könyvben: C# Software Offline 2002 évkönyv 231. oldal

Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!

Copyright © 1999-2012 Animare Software Kft. Minden jog fenntartva!
| Készült: Animare Stúdió | Adatvédelem | Kapcsolat |