A felhőalapú technológiákra váltás egy izgalmas kihívás - ha tudod miként kezdj neki! Ebben a cikkben szeretném megosztani...
MVVM: Adatkötési technikák
Gulyás GáborAz 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:
[ecko_code_highlight language=”javascript”]TextView msgBox = (TextView)findViewById(R.id.msgBox);
msgBox.setText(user.getName());[/ecko_code_highlight]
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.
[ecko_alert color=”gray”]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.[/ecko_alert]
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:
- Elkészítjük a ViewModel-t.
- Létrehozzuk a ViewModel-ben azokat az adattagokat, amikre majd az adatkötést elvégezzük – logikus nemde? 🙂
- 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:
[ecko_code_highlight language=”scheme”]<TextBlock Text=”{Binding User.Name}” />[/ecko_code_highlight]
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.
- OneTime: A felület kirajzolásakor megnézi az értéket, kiírja, de onnantól nem foglalkozik a változásokkal.
- OneWay: Kiírja a felületen az adattag értékét, emellett azonban figyel a háttérben történő módosításokra és azokat a felületen is megjeleníti.
- TwoWay: A OneWay-hez hasonló, azonban a módosításokat a másik irányba is menti, tehát ha a felületről módosítjuk egy bemeneti mező értékét, a módosítás az adattagon is megtörténik.
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:
[ecko_code_highlight language=”scheme”]<TextBlock Text=”{Binding User.Name, Mode=OneWay}” />[/ecko_code_highlight]
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:
[ecko_code_highlight language=”c#”]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));
}
}[/ecko_code_highlight]
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!
-
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.
-
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 🙂
-
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.
-
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/
-