bhawk.hu – Magyar fejlesztői blog

bhawk.hu – Magyar fejlesztői blog


2019. július
h k s c p s v
« máj    
1234567
891011121314
15161718192021
22232425262728
293031  

Kategória


MVVM: Adatkötési technikák

Gulyás GáborGulyás Gábor

Az MVVM sorozat első részében már megkezdtük ismerkedésünket ennek a mintának az alapelveivel, láthattuk milyen egységekre bontja szét alkalmazásunkat. A most következő részben az adatkötési technikákat (Data Binding) fogom bemutatni, hogy a háttérkódban összegyűjtött adatokat valamilyen módon végre megjeleníthessük felületünkön.

Az adatkötés célja, hogy a ViewModel-ben található, példányosított objektumokat valamilyen formában megjelenítsük a felhasználó számára. A legtöbb platformon sajnos a legkézenfekvőbb megoldás ennek a megvalósítására, hogy hivatkozunk a felületi elemre, majd annak egy adattagját felülírjuk.

Android esetében ez a következőképpen történne:

TextView msgBox = (TextView)findViewById(R.id.msgBox);
msgBox.setText(user.getName());

A felületi elem kikeresését követően egy metóduson keresztül írjuk felül az értéket. Tegyük fel, hogy a felület egy űrlap, 20 elemmel. Ha rányomunk a mentés gombra, akkor minden egyes elemen egyesével végig kéne mennünk, beolvasni a tartalmát, majd pedig felülírni a példányosított objektumban a megfelelő adattagok értékeit. Ez egyrészt nagyon kényelmetlen is, valamint rengeteg felesleges kódot jelent számunkra.

Az adatkötés (Data Binding) pontosan ezt hivatott kiküszöbölni: a felületi elemek adattagjainak az értékeként mi egy referenciát adunk át, hogy mely példányosított objektumból, mely adattag értékét szeretnénk ott megjeleníteni. Az már a mi dolgunk, hogy ez az objektum, valamint az adattag létezzen, mivel fordítási időben nem tudjuk, hogy milyen típus is az adott referencia.

Megjegyzem, a Windows 10 esetében már változtattak a Data Binding módszereken és már van lehetőség arra, hogy megadjuk a referencia érték típusát, azonban ez más szempontból hasznos számunkra. Erről majd egy másik alkalommal beszélnék.

 

Egy egyszerű adatkötés

Alkalmazásunkat a Windows 10 platformon fogjuk megírni, melyen bemutatom az adatkötés működését.

Az adatkötés definiálását három dolognak kell megelőznie:

  1. Elkészítjük a ViewModel-t.
  2. Létrehozzuk a ViewModel-ben azokat az adattagokat, amikre majd az adatkötést elvégezzük – logikus nemde? 🙂
  3. Beállítjuk a DataContext-et a felületünkhöz a konstruktorban: a DataContext határozza meg, hogy milyen adathalmazból fogjuk megadni majd az adatkötéseket. Ha ezt hibásan adjuk meg, vagy egyáltalán nem adjuk meg, akkor az adatkötés nem fog működni.

Nézzünk egy nagyon egyszerű példát:

<TextBlock Text="{Binding User.Name}" />

Egy adatkötés mindig ugyanebben a sémában épül fel, függetlenül attól, hogy mely felületi elem mely adattagjához adjuk meg: {Binding AdattagElérésiÚtvonala}. Ha a DataContext-et helyesen adtuk meg, akkor az ott átadott ViewModel-ben egy User objektum Name adattagjának az értéke fog megjelenni a felületen. (Megjegyzem, nem kötelező ViewModel-t átadni a DataContext-ben, erre semmilyen szabály nincs. Sőt, akár a felületen belül más-más DataContext is megadható az elemekre.)

És mi történik akkor, ha a háttérben módosítjuk a Name értékét? Megjelenik a felületen az új érték igaz? Nem. Semmi sem fog történni és itt jutunk el oda, ahol az adatkötések típusait nézzük meg.

Adatkötés típusok

Az adatkötéseket három különböző típussal adhatjuk meg, rögtön meg is nézzük miben különböznek.

Megjegyzés: Általában a OneWay az alapértelmezett típus a legtöbb felületi elemen.

Oldjuk hát meg, hogy a felületünkön a Name átírásával változzon felhasználónk neve, ehhez adjuk meg az adatkötés típusát a deklarálásnál:

<TextBlock Text="{Binding User.Name, Mode=OneWay}" />

Ezzel megvolnánk, azonban a módosítást követően még mindig nem változik az érték a felületen és bánatosan a kódot nézve azon gondolkozunk, mit ronthattunk el. Ahhoz, hogy ez a megoldásunk működjön, szükségünk lesz még egy lépés beiktatására – jeleznünk kell a felületnek, hogy megváltozott az adatkötésben szereplő adattag értéke!

INotifyPropertyChanged

Az INotifyPropertyChanged nevéből adódóan egy interface, melyet implementálnunk kell az osztályunkban. A kódunkat kiegészítve a következőt kell, hogy kapjuk:

public class User : INotifyPropertyChanged {

    private string _Name;
    public string Name {
        get
        {
            return _Name;
        }
        set
        {
            _Name = value;
            OnPropertyChanged("Name");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

}

A kódban látható, hogy az adattag setterében meghívtuk az OnPropertyChanged függvényt, melynek paraméteréül az adattag nevét adtuk meg. Ezzel a hívással úgymond jelezzük a felületnek, hogy “Hékás, módosult ennek az adattagnak az értéke, keresd meg a hozzá tartozó adatkötéseket és módosítsd az értékeket!”.

Példa alkalmazás

Az adatkötésekről készült példakód a következő webcímen érhető el: https://github.com/Bhawk90/SampleCodes/tree/master/MVVM-Binding-Simple
A kódpéldában szerepelnek kommentek, segítségek, javaslatok! Érdemes elolvasni őket!

Tetszett a cikk? Oszd meg a véleményed, vagy mondd el miről olvasnál szívesen!

Minden ami Microsoft technológia! Több mint 8 éve foglalkozom programozással, ez idő alatt pedig rengeteg nyelvet elsajátítottam, leginkább a C#-ot kedvelem! Jelenleg szoftverfejlesztőként dolgozom!

Comments 9
  • Laczik Dávid
    Posted on

    Laczik Dávid Laczik Dávid

    Válasz Author

    Jó, hogy végre van érthető MVVM segítség magyarul 😀
    Viszont van egy olyan probléma, hogy nekem nem működött a fenti módszerrel. Én a XAML fájlba használtam az xmlns:vm-t és csak úgy ment.


    • Gulyás Gábor
      Posted on

      Gulyás Gábor Gulyás Gábor

      Válasz Author

      Melyik résznél akadtál el? Ha a ViewModel-t kódban példányosítod, akkor semmiképpen ne feledkezz meg a DataContext beállításáról sem, mert ott fogja keresni a változót amire az adatkötést végeznéd.

      Vagy más jellegű a probléma? 🙂


  • Laczik Dávid
    Posted on

    Laczik Dávid Laczik Dávid

    Válasz Author

    Nem akadtam el 🙂
    Példányosítottam a VM-t a kódban, hozzáadtam a DataContext tulajdonsághoz, de nem volt jó. Persze először magamtól, így azt gondoltam elrontottam. Megnéztem a kódodat, csináltam egy ugyan olyat és utána se volt jó nekem. Szóval nem tudom mi a gond, de mindenesetre így működik xmlns használatával 🙂


    • Gulyás Gábor
      Posted on

      Gulyás Gábor Gulyás Gábor

      Válasz Author

      A GitHub-on lévő forráskódot ha letöltöd, azzal működik? Érdemes debug közben az Output-ot is nézni a Visual Studio-ban, mert ott megjelenhet olyan, hogy nem létező tulajdonságra próbálsz Bind-olni 🙂


      • Laczik Dávid
        Posted on

        Laczik Dávid Laczik Dávid

        Author

        Meglett a hiba 🙂
        Az volt a gond, hogy Bind közben valamiért a ViewModel példány nevével próbáltam hivatkozni, de ugye a ViewModelben példányosított Modellel kéne.
        Kár, hogy nem dobja be a Bind lehetőségek közé a Model példányt.


      • Gulyás Gábor
        Posted on

        Gulyás Gábor Gulyás Gábor

        Author

        Örülök, hogy meglett a hiba oka! 🙂


  • S. Katalin
    Posted on

    S. Katalin S. Katalin

    Válasz Author

    Kedves Gábor!

    Nagyon örülök és gratulálok a magyar dokumentációért. Ha nem szeretnénk a View kódjában az InitializeComponent()-en kívül egyebet írni, akkor hová kerülne a this.DataContext = ViewModel; ?
    A másik kérdésem az lenne, hogy hogyan oldaná meg MVVM-ben egy olyan többnyelvű alkalmazást, amelyben az alkalmazás indulásakor kiválasztanánk egy nyelvet és utána azon a nyelven jelenne meg minden felirat az ablakokban? Láttam a neten, hogy többféle megoldás létezik, de kevés közülük olyan amelyik helyesen követi az MVVM-t.
    Köszönettel, Katalin.


    • Laczik Dávid
      Posted on

      Laczik Dávid Laczik Dávid

      Válasz Author

      Ha nem a View kódjában van a ViewModel hívás akkor a használni kívánt xaml állományba kell beírni az alábbit xmlns:vm=”using:project_name.ViewModel_folder” . Majd a elem között a tag használatával kiválasztani a ViewModelt. Például: http://tinyurl.hu/rFsk/


    • Gulyás Gábor
      Posted on

      Gulyás Gábor Gulyás Gábor

      Válasz Author

      Üdvözlöm Katalin!

      Elnézését kérem a késői válaszért, bízom benne, hogy még tudok segíteni a kérdésben!

      1. Másik lehetőségünk a XAML-ben történő DataContext meghatározás. Sajnos az utóbbi hetekben nem volt túl sok időm a cikkek írására, azonban igyekszem mihamarabb ezt is bemutatni, mivel az MVVM Light erre egy hasznos, de viszonylag komplex megoldást kínál, azonban mindenképpen érdemes megismerkedni vele.

      2. Többnyelvű alkalmazások létrehozására valóban rengeteg lehetőség van. Leginkább a resx Resource fájlok használatát javaslom, korábban ugyanezzel oldottam meg én is a többnyelvűség kérdését:
      http://stackoverflow.com/questions/1142802/how-to-use-localization-in-c-sharp

      Ennek persze platformtól függően más lehet az implementálási módja, pl egy WPF, vagy éppen WinRT alkalmazás esetében. A lokalizáció esetében úgy gondolom inkább a platform megkötéseit és ajánlásait érdemesebb figyelembe venni, mint az általunk használt mintát – sok esetben a kettő nem befolyásolja egymást.

      Gábor


This site uses Akismet to reduce spam. Learn how your comment data is processed.