Mvvm minta és az oldal navigáció

Mindenki, aki már dolgozott együtt a WPF, valószínűleg ismeri a minta MVVM (linkek végén közölt a cikket). Végtére is, a koncepció egyszerű és MVVM legalább ösztönösen egyértelműnek kell lennie, egyéb előnyök. Ha azt akarjuk, hogy megnyilvánulni minden dicsőség, a lehető legkisebb legyen, hogy a logika a «Code Behind» felhasználói vezérlés (UserControl), és minden esetben ne használja közvetlen kapcsolatot a UI belül ViewModel'ey. Ez a megközelítés kapsz egy nagy nyereséget formájában lehetőségét vizsgáló ViewModel'ey elkülönítve az ellenőrzések. Egy másik jó gyakorlat az, hogy minimalizáljuk a teremtés másolatok ViewModel'ey közvetlenül irányít. Ijesztő, ha az ellenőrző magának ViewModel létrehoz egy bizonyos típusú - ebben az esetben csak nehezebb lesz, hogy egy vezérlő néhány próbabábu. Ellenkező esetben a dolgok, amikor egy szülői foglalt létre ViewModel'ey más képernyők, mert akkor a kód válhat, nem teszt egy csomó spagetti. Ha létrehozására ViewModel'ey találkozik más ViewModel'i, a vizsgálat lesz sokkal könnyebb.

Képzeljük kérelmet a navigációs sáv, több képernyő és a párbeszédpanelek. Valami ehhez hasonló alábbiakban mutatjuk be.

Mvvm minta és az oldal navigáció

Láthatjuk több szervezet: a fő ablak a navigációs gombjai, az aktuális oldal és a dialógus ezen az oldalon. A mi alkalmazás, a lapozás navigációs lehetne használni HyperLink helyett helyezve a gombok hyperlink TextBlock, mint a tartalom. HyperLink van egy tulajdonsága, amely meghatározza a neve a keret, amelyben elvégzésére az átállás az új oldalt. És jó érzés, de úgy tűnik, nehéz HyperLink át a kívánt oldalt ViewModel'i.
Láttam a neten egy pár megoldás erre a problémára:

  • A Frame.Navigated esemény a fő alkalmazás ablak mögötti kódot, akkor a hozzáférés tartalmat betölteni a keretet, és tegye vissza az azonos létrehozott kód mögött ViewModel. Így a teremtés ViewModel'ey összes oldal fog koncentrálódni egy processzor, hosszú láb ruhával, ha ... else if ... vagy kapcsolót. Az a tény, hogy a vizsgálatok a «Hard kódolt» navigációs folyamat rendkívül nehéz automatizálni, én csendben.
  • A másik megoldás az, hogy hozzon létre egy példány oldal ViewModel'i és alatta, a podkladyvanie ViewModel'i oldal DataContext fokon és hívja Navigate keretben a továbbítására létrehozott példányt oldal. Ez a megoldás egy kicsit jobb, mint az előző, de még mindig nem «MVVM utas».
  • A harmadik megoldás is lehet nevezni a könyvtárak PRISM. Ezt alkalmazzák a nagyvállalati alkalmazás ágazatban történő végrehajtására az összetett UI. Ha ismeri AngularJS, meg fogja érteni, hogy mi az. Végre egy RegionManager, amely rögzíti a UI. Ezután révén létrehozott manager nevű példányosıtási Control nekoemomu nevét, mint a feladat a szükséges adatokat az összefüggésben. Ez a funkció hasonló ahhoz, amit már megvalósított NavigationService WPF.

Az első két megoldás - egy nyilvánvaló mankó. Prism - egy UI keretrendszer készítmény. Fektessen be a tanulmány, természetesen szükség van, de a kis alkalmazások (proof of concept, például.) Használata a dolgok, mint NOB és a PRISM, lehet, hogy nem praktikus.

Mi a legegyszerűbb megoldás az lenne többé-kevésbé zökkenőmentesen illeszkedik MVVM kontextusban? A Page osztály Silverlight már túlterhelt módszer OnNavigatedTo. Ebben a módszerben, lenne kényelmes, hogy a ViewModel, továbbított NavigationService.Navigate (URI uri, objektum navigationContext) a második paraméter. Azonban a WPF oldal ebben az eljárásban nem. Legalábbis én nem találtam meg, vagy azzal egyenértékű. Szükségünk van egy közvetítő vagy, ha azt szeretnénk, egy menedzser, aki figyelemmel kíséri az átmenetek oldalak között, és áttérni a módszert paramétert a kívánt DataContext ViewModel. A végrehajtás a navigációs menedzser és lesz szó ebben a cikkben.
A következő részben fogok szólni a vonatkozó alapvető megoldások, menedzser navigációt. Akkor, akkor megtudjuk, hogy meg kell tenni a UI és ViewModel rétegeket. Időt takaríthat meg, akkor olvassa el a „Navigáció Manager” rész, és a többi gondolkodni során problémáik megoldásában.
Kit érdekel, csak nézd meg a kódot, akkor menj el a lerakatot GitHub.

navigáció menedzser

Ennek a menedzsernek van megvalósítva egyelem¶ ellenőrizte egy példányát az null (az úgynevezett kettős-Check Zár Singleton. Singleton többszálas verzió). A Singleton - ez az én preferencia. Szóval könnyebb irányítani az életciklus. Valószínűleg elég lett volna, és egy egyszerű statikus osztály.
Kódelhelyezés Singleton, lásd alább.

A kód a fent bemutatott láthatjuk, hogy az ingatlan Bíróság tettem magán. Ezt úgy végezzük, az egyszerűség kedvéért, hogy a külső nem benézett semmit extra. Azt is, hogy a gyakorlatban szükség lehet annak érdekében, hogy nyilvánosan elérhetővé. Ahelyett, hogy a magántulajdon egyke például én hoztam létre a közszolgálati navigációs szolgáltatása segítségével (típus NavigationService), amely továbbítja a hívásokat a saját példányát az egyedüli. Lehetséges volt, hogy nem az ellenkezőjét, de akkor az összes hívás, hogy a külső is lehet véghezvinni egy példánya, azaz

Válassza ki a lehetőséget, hogy tetszik. Azt hiszem, az utóbbi lehetőség könnyebb de szükség további végrehajtása a statikus tulajdonságok és módszerek. Ezért válhat előnyös megnyitni egy példány tulajdonság (Navigation.Instance) végrehajtására az új funkciók.

Service ingatlan az egyedüli tart egy hivatkozás egy példányát NavigationService Frame, amelyben a végrehajtani kívánt oldal-átmenetek. Rendelje meg ezt a linket vonatkozású lehetséges mind az alkalmazás indulásakor (a eseménykezelő Loaded fő ablak) és bármely más, később a hívást az egyik navigációs módszerekkel.

A fenti példában, mi hozzá a navigátor NavigationService Frame fő ablakban. Ehelyett a fő ablakban lehet bármilyen szabályozás, de meg kell, hogy NavigationService terhelt esetén a kontroll. Ezt megelőzően esemény, akkor kap null. Részletesebben az életciklus-szabályozás és NavigationService én még nem vizsgálták.
Egy alternatív forgatókönyv, talán alkalmazását javasolja az ChildWindow WPF Toolkit Extended. amely épített egy másik keret. Lehetőség van ebben az esetben, egy ideiglenes helyettesítő NavigationService mi navigátor, hogy az átmenet az ilyen párbeszédben. Ez automatizálja felett Binding podgruzku különböző képernyők a párbeszédpanelek. De a forgatókönyv ez a használat úgy tűnik, nagyon egzotikus, mert nem fogok festeni részletesen. Ha egy ilyen forgatókönyv érdekes, írok egy külön cikkben.

navigációs szolgáltatás tulajdonság

Jó, a szetter (és az állami irányítási módszerek is) hiányzik a használata zár. De általában, ha az alkalmazás párhuzamosan a legnagyobb kihívást a navigációs módszer váltja NavigationService. valószínű, hogy valami végre. Míg az egyszerűség kedvéért teszünk zár nélkül. de már figyelmeztette.

Az alábbiakban nyilvános navigációs módszerekkel.

A fenti kódot, azt tapasztalhatja a használata „_resolver”. A NOB mondok róla. Röviden, ez egy egyszerű részleges végrehajtása a Container inverzió az ellenőrzés.

A navigációs menedzser végre egy részhalmaza navigációs módszerek NavigationService. amely elegendő a legegyszerűbb esetben. Már csak azt, hogy egy továbbított ViewModel DataContext tulajdonság a cél oldalon. Ez történik az eseménykezelő navigálással (lásd. Az alábbi kód).

Navigált esemény feldolgozása

Az eseménykezelő navigálással Frame kísérletek, hogy a tartalom az oldal típusát. Így azok feldolgozása csak átmenetet oldal. Az összes többi szűrő. Ha azt szeretnénk, akkor távolítsa el a „vasfüggöny”. Abban az esetben sikeres vet továbbítják az ingatlan érvek ExtraData fokon ViewModel'i esemény kerül a DataContext nyitóoldal. Ez mind a navigációs vezetője.
Továbbra is létrehozhat egy összeállítás megvalósításával oldalak és összeszerelés ViewModel'ey. Rájöttem Segítők egység, amely elhelyezni a kódot végrehajtási RelayCommand ViewModel'ey. Ha az erő és idő, menjen a következő szakaszok leírják a végrehajtás a UI és ViewModel'ey. Ha nem, az alábbiakban foglaljuk össze, mit kell végrehajtani.
létre kell hozni egy külön ViewModel minden oldalon. Ezek a „Real” ViewModel'i példányosítható szülői MainViewModel az „inverzió control” (lásd. NOB fejezet). Főoldal ViewModel DataContext helyezzük a fő ablakban, de ugyanolyan sikerrel lehetne futtatását az XAML egy statikus erőforrás az erőforrás szótárban a fő ablak, vagy akár szinten az egész alkalmazást. Ebben az esetben a DataContext kötéseket kell adni valamit, mint Source =. De akkor nem kell aggódnia, hogy vajon örökölte a megfelelő helyen DataContext logikai szülő.
A MainViewModel hoztam létre néhány parancs. Az egyik, hogy menjen a megadott string name in CommandParameter oldal (enélkül adatátvitel összefüggésben). Más csapatok szerepeltetnek delegáltja Execute átmenet adott név nyitóoldal keresztül CommandParameter adatok összefüggésben. További részletek, akkor mehet a GitHub vagy olvassa tovább ezt a cikket.

összeszerelése ViewModels

Ebben a berendezés rendelkezik egy alap ViewModel, amely végrehajtja INotifyPropertyChanged.

A fennmaradó ViewModel'i származnak, és jelenleg nagyon egyszerű. Ezek tartalmaznak egy karaktersorozat tulajdonság egy egyedi nevet (lásd. Az alábbi példát).

Itt jegyezzük meg, csak olvasható tulajdonság, és anélkül, hogy RaisePropertyChanged (...) nem számít, hogy hol van. Ebben az esetben ez történt az egyszerűség kedvéért. A gyakorlatban az ilyen tulajdonságokkal ViewModel'ey fordul elő, de nem gyakran, mert Kötődés ezek a tulajdonságok a munka csak egyszer. Még ha adhatok egy szetter nélkül RaisePropertyChanged (...), a Binding továbbra is „egyszeri”.

MainViewModel már sokkal nehezebb. Mint írtam röviden az előző részben, akkor bizalmasan ViewModel'i és végrehajtása navigációs parancsok. Az én esetemben, privát ViewModel'i létre csak egyszer, az úgynevezett „feloldó»és a«mikor MainViewModel elindulni. Így rájöttem, getter ezek ViewModel'ey.

A mezők inicializálása a kivitelező MainViewModel:

„_resolver” ebben az esetben - egy másik inverzió a kontroll tartályt, amelyet a későbbiekben a megfelelő fejezetben. Abban a pillanatban, a feloldó egyszerűen kihúzza a szótárban küldött megfelelő továbbított neve ViewModel. Azt is érdemes megjegyezni, hogy a gyakorlatban, akkor szükség lehet, hogy a teljes körű megvalósítása a mezők és tulajdonságait magán ViewModel'ey. Ez már folyamatban van agy.

Csapatok esetemben végre meghatározza a get és set. és inicializálása esetekben helyezni egy külön funkciót. A jelenléte alkotóinak csapat lehetővé teszi számomra, hogy helyettesítse az egyes csapat kívül a jelenlegi ViewModel. Ez a megközelítés lehetővé teszi, például, hogy módosítsa a válasz a párbeszédablak Kattintson az „OK”, ha ez köti kötődése a megfelelő csapatnak benne (dialógus) belső ViewModel. Azonban egy ilyen forgatókönyv nagyon egzotikus és végre kell hajtani anélkül alkotóinak csapatok.

Felhívjuk figyelmét, hogy az az út, továbbítjuk alias nyitóoldal. Ezek álnevek tettem állandók a navigációs vezetője, de általában a legjobb hely számukra az XML-fájl beállításait, vagy egyszerűen csak egy szöveget szótárban.

A fő ablak és az összeszerelés oldalak

Itt vagyok megint az egyszerű néző teszt alkalmazás.

Mvvm minta és az oldal navigáció

A bal oldalon négy gomb található. Az első gomb van kötve GoToPathCommand csapat, és megy az 1. oldalon adatokat anélkül összefüggésben. A rendszerváltást követően az oldal adatai nélkül összefüggésben helyett a tényleges értéke ViewModel'i helyettesíteni fogja a paraméter értékét FallbackValue Binding objektum. A többi gombot kapcsolódnak a „privát” csapatok a küldött a megadott parancsálnév kívánt oldal oldal.

Markup és kódját a fő ablakban

Építsd oldalakon négy oldalt: 1. oldalon, Page2, Page3, Page404. Az első két csak szöveget tartalmaznak dobozok, amelyek kötődnek a tulajdonában van az adott privát ViewModel. A harmadik voltam egy kicsit bonyolult, hogy hajtsák végre a MVVM másik probléma, nevezetesen a probléma ListBox.SelectedItems kötődnek a ViewModel. Ez egy külön kérdés, amely véleményem szerint megérdemel egy külön cikket. Akkor nézd meg a jelölést légterelő alacsonyabb kamatot.

NOB (a kontroll megfordítása)

Sajnos nem tudok részletesen leírja a megközelítés ebben a cikkben. Hangerő és olyan nagy. De meg lehet tanulni a szükséges ismereteket, például a cikkek Habré. Szintén rengeteg források Ráguglizhatsz. Röviden, a „inverziós kontroll” egy módja annak, hogy megszüntesse a közvetlen kapcsolatot az egyik szerelvényt egy másik szerelvény. Függőség Injection végzi speciális „konténer”, hogy a konfigurációs fájlok felismerik, milyen konkrét osztályok és a közgyűlések elindítani a felületet, és jelzik a nevét a szakasz a konfigurációs fájlban. Meg kell vallanom, hogy én kód NOB nem hajtják végre teljes mértékben. Hogy őszinte legyek, objektív, és nem ez volt. Természetesen a koncepció NOB a kódot megpróbáltam, hogy tükrözze, és megpróbálta megmutatni, hogyan lehet a kód kevésbé összefüggő.
Az alábbiakban konténer interfészek és végrehajtását.

Ezek a felületek jár bizonyos szerződések különféle megvalósítások oldalak és ViewModel'ey konténerek. Abban a pillanatban tettem a két implementációt, akkor semmiképpen nem alkalmazható a valós projektekben.

Megvalósításai teszt konténerek

Ez csak egy „baba” konténerekben cserélnek valami szabályozható, mint a Unity könyvtárban. Mivel a felület is jobb lenne használni valami hasonló IUnityContainer. de nem akarja terhelni solyushen további referencia és bonyolítja a megítélése annak végrehajtását a navigátor. Különösen azért, mert akkor válasszon más NOB könyvtár helyett a Unity.

további irodalom