MVVM – WPF.

Slides:



Advertisements
Hasonló előadás
A kártyanyomtatás fortélyai Csákvári Krisztián Kártya és címke gyártás
Advertisements

A családsegítő és gyermekjóléti szolgálatokat érintő változások A család és gyermekjóléti szolgáltatás.
TÖMÖRÍTÉS. Fogalma A tömörítés egy olyan eljárás, amelynek segítségével egy fájlból egy kisebb fájl állítható elő. A tömörítési arány függ a fájl típusától,
Bevezetés a C# nyelvbe Az alapok összefoglalása Farkas Csaba.
Szabadtéri rendezvények. A TvMI vonatkozik: OTSZ szerinti szabadtéri rendezvényekre szabadtéri rendezvény: az 1000 főt vagy az 5000 m 2 területet meghaladó,
Követelményelemzés – követelményspecifikáció A szoftverfejlesztés kapcsán az elemzés speciálisan egy kezdeti szakaszt jelöl, amelynek alapvető feladata.
Bemutatkozás Fodor Noémi Gépészmérnök – mérnöktanár Környezetirányítási szakértő TAR-ZERT Auditor Minőségirányítási vezető.
P.XML architektúra Alkalmazás fejlesztés és kiszolgálás Java és XML alapokon Bukodi László
1 Az önértékelés mint projekt 6. előadás 1 2 Az előadás tartalmi elemei  A projekt fogalma  A projektek elemei  A projekt szervezete  Projektfázisok.
Hogyan teljesíthetjük a HpT 13§B követelményeit Egy vállalati Compliance Adatbázis terve Dr Lőrincz István Associator Kft.
Dr. Szűcs Erzsébet Egészségfejlesztési Igazgatóság Igazgató Budapest, szeptember 29. ÚJ EGÉSZSÉGFEJLESZTÉSI HÁLÓZATOK KIALAKÍTÁSA ÉS MŰKÖDTETÉSE.
Turisztikai desztináció- menedzsment és klaszter Tóthné Bánszki Zsuzsa Észak-magyarországi Regionális Fejlesztési Ügynökség Kht.
CÉLCÉLCSOPORT  Egészségügyi szakmai tájékoztatás és betegtájékoztatás, az egészséges életvitelhez szükséges információk szolgáltatása, publikálása, áttekint-
Informatikai rendszerek általános jellemzői 1.Hierarchikus felépítés Rendszer → alrendszer->... → egyedi komponens 2.Az elemi komponensek halmaza absztrakciófüggő.
Oktatói elvárások, oktatói vélemények a hallgatókról Cserné dr. Adermann Gizella egyetemi docens DUE.
Környezeti fenntarthatóság. A KÖRNYEZETI FENNTARTHATÓSÁG JELENTÉSE A HELYI GYAKORLATBAN Nevelőtestületi ülés,
EU pályázati programok A szervezet / változások 1.A pályázók adminisztrációs terheinek csökkentése a projektfejlesztési, pályázati szakaszban.
Neumann János Informatikai Kar
Internet tudományos használata
ERASMUS+ DISSZEMINÁCIÓS PLATFORM
Gazdasági informatika - bevezető
Fájlkezelés.
A szerkezetátalakítási programban bekövetkezett változások
Valószínűségi kísérletek
A kérdőívek, a kérdőívszerkesztés szabályai
WE PROVIDE SOLUTIONS.
Programstruktúrák.
A CMMI modell alkalmazása SOA-környezetben
Szupergyors Internet Program (SZIP) Jogi akadálymentesítés megvalósítása: Jogalkotással is támogatjuk a fejlesztéseket dr. Pócza András főosztályvezető.
videós team Team vezetője: Tariné Péter Judit Tagok:
Adatok importálása, rendezése és szűrése
Az Európai Uniós csatlakozás könyvtári kihívásai
Programozás III. Gyakorlás.
LabVIEW bevezetéstől a feszültség-áram karakterisztikáig Vida Andrea
Kommunikáció a könyvvizsgálatban
SNMPView Készítette: Varga Gábor
Programozás I. Gyakorlás egydimenziós tömbökkel Többdimenziós tömbök
Követelményelemzés Cél: A rendszer tervezése, a feladatok leosztása.
Dependency Injection Moq Feladat
Visual Studio Code Metrics
Animációk.
Adatbázis-kezelés (PL/SQL)
☺ Programozási környezetek Validátorok Fazekas Judit PTI 2010.
Közigazgatási alapvizsga a Probono rendszerben
Körmendi Dániel MAS Meeting Scheduler.
Rendszerfejlesztés gyakorlat
Az Endnote bibliográfia adatbázis-kezelő szoftver alapvető használata november Skultéti Attila
CONTROLLING ÉS TELJESÍTMÉNYMENEDZSMENT DEBRECENI EGYETEM
Tájékoztató az Önkormányzati ASP Projektről
RUGÓK.
Informatikai gyakorlatok 11. évfolyam
Elektronikai Áramkörök Tervezése és Megvalósítása
Beépített assetek (Standard Assets).
Informatikai gyakorlatok 11. évfolyam
B M Java Programozás 4. Gy: Java GUI IT A N Tipper, MVC kalkulátor
Oracle Adatbázisok kezelése c#-ban
A Microsoft SharePoint testreszabása Online webhely
A távoli asztal, valamint az Endnote használata a távoli asztalon
TÁRGYI ESZKÖZÖK ELSZÁMOLÁSA
B M Java Programozás 9. Gy: Java alapok IT A N Adatkezelő 5.rész
Vasbeton falvasalás megadása és ellenőrzése EC2 szerint
B M Java Programozás 2. Gy: Java alapok IT A N Adatszerkezetek
KRÉTA-ESL Bemutató.
SQL jogosultság-kezelés
Tájékoztató az EPER pályázati folyamatáról
JAVA programozási nyelv NetBeans fejlesztőkörnyezetben I/13. évfolyam
Informatika Oktató: Katona Péter.
A POWERPOINT 2007 újdonságai
Algoritmusok.
IT biztonsági monitoring eseményfelügyelet, bizonyítékok,
Előadás másolata:

MVVM – WPF

Tartalom WPF MVVM IoC DI MVVM LIGHT, PRISM 5.0 Entity Framework

WPF-Windows Presentation Foundation DEMO

MVVM (Model-View-ViewModel) Modell (Model) - Üzleti logika Entity Framework (adatbázis osztályok) – Perzisztencia – hosszú távú adattárolást és adatelérést biztosítja Események, visszatérési értékek - Nézetmodell Nézetmodell (ViewModel)– Közvetítő réteg Reakciók a View-ben történt eseményekre Hívások – Model metódusai Adatok továbbítása – View felé Nézet (View) – Felhasználói felület ~100 % XAML DataContext tulajdonság – kapcsolódás a ViewModel-hez A ViewModel-ben lévő ObservableCollection nézetét, a Collection- ViewSource-t használja

MVVM – régetek közötti függőségek

Általános konvenciók..?!!! gyakorikeredesek.hu Nincs hivatalosan kiadott kötelező érvényű implementáció!!! Mit, hol kell mindenképp implementálni. Cél a rétegek közötti függőségek csökkentése (loose coupling) Egyik réteg sem függhet a másik konkrét megvalósításától, és nem avatkozhat be a másik működésébe Ennek eléréséhez függőség befecskendezést (dependency injection) használunk. a nézetmodellt a nézetbe egy tulajdonságon keresztül fecskendezzük be (setter injection) a modellt a nézetmodellbe, a perzisztenciát a modellbe konstruktoron keresztül helyezhetjük (constructor injection)

A programegységek példányosítását és befecskendezését az alkalmazás környezete (application environment) végzi ismeri és kezeli az alkalmazás összes programegységét (absztrakciót és megvalósítást is) nem az adott komponens, hanem a környezet dönti el, hogy a függőségek mely megvalósításai kerülnek alkalmazásra (Inversion of Control, IoC) a környezetet egyszerű esetben megadhatja az alkalmazás (App), de használhatunk külön komponenst is a környezet hatásköre kibővíthető a globális, teljes alkalmazást befolyásoló tevékenységekkel (pl. időzítés)

Előnyök könnyebb tesztelhetőség (nincs benne a View-ban az üzleti logika) kód-újrafelhasználás (a View code mögöttes kód (behind code) részének csökkentése, tényleg csak ami a View-hoz szükséges) rugalmasabb újrafelhasználás (pl. Unitiy, PRISM esetén) átláthatóbb működés (nagyobb rendszereknél) elkülönített, egymással párhuzamosan végezhető munkálatok a terméken (designer, coder)

Egy lehetséges implementáció

Eszközök Egyszerű alkalmazásoknál nem célszerű, mivel hosszabb tervezést és körülményesebb implementációt igényel Megvalósításához több eszközt kell használnunk: felület és nézetmodell közötti adattársítás (Binding) az adatokban történt változások nyomon követése a nézetmodellben (INotifyPropertyChanged) tevékenységek végrehajtása eseménykezelők használata nélkül, parancsok formájában (ICommand) a nézetmodellben

Adatkötés Az adatkötés (data binding) során függőségeket adhatunk meg a felületen megjelenő elemek tulajdonságaira egy adott vezérlő valamilyen függőségi tulajdonságát (cél) tudjuk függővé tenni valamilyen objektumtól, vagy annak egy tulajdonságától (forrás) pl. egy szövegdobozban tárolt szöveget kiírathatunk egy címkére így közvetett módon (anélkül, hogy a konkrét vezérlőhöz hozzáférésünk lenne) tudunk egy tulajdonságot állítani A kötést (Binding) a függőségi tulajdonság értékeként hozzuk létre forrás objektum (Source, ElementName) és tulajdonság útvonal (Path) megadásával, pl.: <TextBox Name="textBoxName" /> <!-- forrás (szövegdoboz) --> … <TextBlock Text="{Binding ElementName=textBoxName, Path=Text}" /> <!-- cél (címke), a címke mindig ugyanazt a szöveget jeleníti meg, mint ami a szövegdobozban van -->

Adatkötés forrás lehet egy teljes objektum, vagy bármely tulajdonsága, vagy beágyazott tulajdonság <TextBlock Text="{Binding ElementName=textBoxName, Path=Text.Length}" /> <!-- a címke a szöveg hosszát jeleníti meg --> amennyiben egy névvel rendelkező felületi elemhez kötünk, az ElementName, más objektumok, erőforrások esetén a Source tulajdonsággal adjuk meg a forrást a forrás értéke implicit konvertálódik a cél tulajdonság típusára, vagy mi adjuk meg az átalakítás módját (az IValueConverter interfész segítségével)

Adatkötés paraméterezése A kötés többféleképpen paraméterezhető, pl.: a kötés módja (Mode) lehet egyirányú (OneWay), kétirányú (TwoWay, ekkor mindkét objektum változása kihat a másikra), egyszeres (OneTime), … a cél frissítése (UpdateSourceTrigger) lehet változtatásra (PropertyChanged), fókuszváltásra (LostFocus), …

Adatkötés objektumértékhez Adatkötés a felületi vezérlők mellett tetszőleges objektumra, kódban is megadható kódban a cél DataContext tulajdonságának kell megadnunk a forrást a teljes forrás kötése esetén a felületi kódban egy üres kötést adunk meg, pl.: <TextBox Name="textBox" Text="{Binding}" /> <!-- a kötést megadjuk a felületen, de tulajdonságait nem töltjük ki --> textBox.DataContext = "Hello DataBinding!"; // a forrást a kódban adjuk meg

Adatkötés gyűjteményekre Az adatkötés gyűjteményekre is elvégezhető, ehhez olyan vezérlő szükséges, amely adatsorozatot tud megjeleníteni (pl. ItemsControl, ListBox, GridView, …) a vezérlők ItemsSource tulajdonságát kell kötnünk egy gyűjteményre (IEnumerable) <ComboBox Name="comboPersons" ItemsSource="{Binding}" /> … List<String> persons = new List<String> { … }; comboPersons.DataContext = persons; // a teljes lista megjelenik a legördülő // menüben

Adatkötés a teljes felületre Az adatkötés egy teljes ablakra (Window) is elvégezhető az adatkötést kódban adjuk meg, ezért az ablakot is kódban kell példányosítanunk és megjelenítenünk, pl.: MainWindow window = new MainWindow(); window.DataContext = …; // adatkötés az ablakra window.Show(); // ablak megjelenítése az alkalmazás (App) indulásakor (Startup) kell végrehajtanunk a tevékenységeket, pl.: public App() { // kontruktor Startup = new StartupEventHandler(App_Startup); // lekezeljük a Startup eseményt }

Adatkötés változáskövetéssel Ahhoz, hogy a cél tükrözze a forrás aktuális állapotát, követni kell az abban történő változásokat ehhez a forrásnak meg kell valósítania az INotifyPropertyChanged interfészt ekkor a megadott tulajdonság módosításakor kiválthatjuk a NotifyPropertyChanged eseményt, ami jelzi a felületnek, mely kötéseket kell frissíteni az esemény elküldi a megváltozott tulajdonság nevét, ha ezt nem adjuk meg, akkor az összes tulajdonság változását jelzi egyszerűsítésként felhasználhatjuk a CallerMemberName attribútumot, amely automatikusan behelyettesíti a hívó tag (tulajdonság) nevét

Adatkötés változáskövetéssel - Példa class Person : INotifyPropertyChanged { … private String _firstName; public String FirstName { get { return _firstName }; set { if (_firstName != value) { _firstName = value; OnPropertyChanged(); // jelezzük a változást } }

public event PropertyChangedEventHandler PropertyChanged; // az esemény public void OnPropertyChanged ( [CallerMemberName] String name = null) // ha paraméter nélkül hívták meg, a hívó // nevét helyettesíti be { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); } // eseménykiváltás } }

a változáskövetés teljes gyűjteményekre is alkalmazható, amennyiben a gyűjtemény megvalósítja az INotifyCollectionChanged interfészt az ObservableCollection típus már tartalmazza az interfészek megvalósítását, ezért alkalmas változó tartalmú gyűjtemények követésére pl.: ObservableCollection persons = new ObservableCollection { … }; comboPersons.DataContext = persons; // amennyiben a gyűjtemény, vagy bármely // tagjának tulajdonsága változik, azonnal // megjelenik a változás

Parancsok

Parancsok Mivel az eseménykezelők összekötnék a felületet a modellel, nem használhatóak az MVVM architektúrában Az eseménykezelők helyettesítésére a nézetmodellben parancsokat (ICommand) használunk adattársítással kapcsolható vezérlőhöz, annak Command tulajdonságán keresztül megadják a végrehajtás tevékenységét (Execute), valamint a végrehajthatóság engedélyezettségét () a végrehajthatóság változását is jelzi (CanExecuteChanged) A parancsnak adható végrehajtási paraméter is (a vezérlő CommandParameter tulajdonságával)

Parancsok public class MyCommand : ICommand { public void Execute(object parameter) { // tevékenység végrehajtása (paraméterrel) Console.WriteLine(parameter); } public Boolean CanExecute(object parameter) { // tevékenység végrehajthatósága return parameter != null; public event EventHandler CanExecuteChanged; // kiválthatóság változásának eseménye }

Parancsok public class MyViewModel { // nézetmodell // parancs elhelyezése a nézetmodellben public MyCommand ClickCommand { get; set; } … } <Button Content="Click Me" Command="{Binding ClickCommand}" CommandParameter="Hello, world!" /> <!-- parancs megadása adatkötéssel, valamint paraméterrel -->

Parancsok Mivel egy alkalmazásban számos parancsra lehet szükség, nem célszerű mindegyik számára külön osztályt készíteni a parancsoknak egy tevékenységet kell végrehajtania, amely Action típusú 𝜆-kifejezéssel is megadható, míg a feltétel egy Func típusúval a tényleges tevékenységet végrehajtó művelet elhelyezhető a nézetmodell osztályban, így nem kell külön osztályokba helyezni a kódot elég csupán egy parancs osztályt létrehoznunk (legyen ez DelegateCommand) a tevékenység végrehajtásához, és a tényleges tevékenységet a parancs példányosításakor 𝜆- kifejezés formájában adjuk meg

public class DelegateCommand : ICommand { private Action<Object> _execute; private Func<Object, Boolean> _canExecute; // tevékenység és feltétel eltárolása … public DelegateCommand(Action<Object> execute){ _execute = execute; // tevékenység rögzítése } public void Execute(Object parameter){ _execute(parameter); // tevékenység végrehajtása

public class MyViewModel: INotifyPropertyChanged // nézetmodell { // parancs elhelyezése a nézetmodellben public DelegateCommand MyCommand { get; set; }; public void Write(Object parameter) Console.WriteLine(parameter); // tevékenység } … MyCommand = new DelegateCommand(x => Write(x)); // tevékenység tényleges megadása

Parancsok végrehajthatósága A parancs bármikor jelezheti, hogy állapota megváltozott a CanExecuteChanged eseménnyel amennyiben nem végrehajtható, a vezérlő kikapcsolt állapotba kerül az eseményt alapesetben a parancsnak kell kiváltania, de általános parancsok esetén ez nem végezhető el megoldást nyújt a CommandManager osztály, amelynek RequerySuggested statikus eseménye jelzi, ha újra kell vizsgálni az állapotot automatikusan meghívja a rendszer, amikor beavatkozás szükségességét érzi (pl. ha valamilyen tevékenység fut a felületen)

Az alapvető MVVM támogató konstrukciók a nyelvi könyvtárban nem elegendőek a hatékony, gyors fejlesztésre interfészek vannak (pl. INotifyPropertyChanged, ICommand), de nincsenek ősosztályok, gyűjtőosztályok Több olyan programcsomag került forgalomba, amely az MVVM alapú fejlesztést megtámogatja, pl.: Microsoft Prism: támogatja a modul alapú fejlesztést, az MVVM architektúrákat, nézet-dekompozíciót és cserét MVVM Light Toolkit: támogatja az MVVM architektúrát, a többrétegű modellt, komponensek közötti üzenetküldést, alkalmazás környezet kialakítását

MVVM Light DEMO

PRISM DEMO

Entity Framework DEMO

1. példa - Converter

ViewModel - interfészek INotifyPropertyChanged interface –változáskövetés ICommand interface- tevékenységek végrehajtása

ViewModel –ObservableObject.cs using System.ComponentModel; namespace MVVM1.ViewModel { public class ObservableObject : INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChangedEvent(string propertyName) var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); }

ViewModel –DelegateCommand.cs namespace MVVM1.ViewModel { public class DelegateCommand : ICommand { private readonly Action _action; public DelegateCommand(Action action) _action = action; } public void Execute(object parameter) _action(); public bool CanExecute(object parameter) return true; public event EventHandler CanExecuteChanged { add { } remove { } }

ViewModel – Presenter.cs using System.Collections.ObjectModel; using System.Windows.Input; using MVVM1.Model; namespace MVVM1.ViewModel { public class Presenter : ObservableObject { private readonly TextConverter _textConverter = new TextConverter(s => s.ToUpper()); private string _someText; private readonly ObservableCollection<string> _history = new ObservableCollection<string>(); public string SomeText get { return _someText; } set _someText = value; RaisePropertyChangedEvent("SomeText"); }

public IEnumerable<string> History { get { return _history; } } public ICommand ConvertTextCommand get { return new DelegateCommand(ConvertText); } private void ConvertText() AddToHistory(_textConverter.ConvertText(SomeText)); SomeText = String.Empty; private void AddToHistory(string item) if (!_history.Contains(item)) _history.Add(item);

Model – a lehető legegyszerűbb modell namespace MVVM1.Model { public class TextConverter private readonly Func<string, string> _convertion; public TextConverter(Func<string, string> convertion) _convertion = convertion; } public string ConvertText(string inputText) return _convertion(inputText);

View – ConverterWindow.xaml –háttérkód fájl üres!!! <Window x:Class="MVVM1.View.ConverterWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ViewModel="clr-namespace:MVVM1.ViewModel" xmlns:View="clr-namespace:MVVM1.View" Title="ConverterWindow" Height="300" Width="300"> <Window.DataContext> <ViewModel:Presenter/> </Window.DataContext> <View:ConverterControl/> </Window>

View – ConverterControl.xaml- háttérkód fájl üres!!! <UserControl x:Class="MVVM1.View.ConverterControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ViewModel="clr-namespace:MVVM1.ViewModel" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance ViewModel:Presenter}"> <UserControl.InputBindings> <KeyBinding Key="Enter" Command="{Binding ConvertTextCommand}"/> </UserControl.InputBindings> <StackPanel Height="336"> <Label Foreground="Blue" Margin="5,5,5,0">Text To Convert</Label> <TextBox Text="{Binding SomeText, UpdateSourceTrigger=PropertyChanged}" Margin="5"/> <Label Foreground="Blue" Margin="5,5,5,0">History</Label> <ListBox ItemsSource="{Binding History}" Height="200" Margin="5"/> <Button Command="{Binding ConvertTextCommand}" Margin="5">Convert</Button> </StackPanel> </UserControl>

1. feladat Elemezzük az előző programot! Ki honnan örököl , ki mit használ, ki hová van kötve… ? Hogyan lehetne módosítani?

2. feladat Készítsünk egyszerű grafikus felületű alkalmazást, amellyel megjeleníthetjük, valamint szerkeszthetjük hallgatók adatait. a felületen a hallgató keresztneve, vezetékneve és Neptun kódja külön szövegdobozba kerül, és egy szövegcímkében megjelenik a teljes neve, ezeket adatkötéssel fogjuk a hallgatóhoz (Student) kötni, amely jelezni fogja a változást (INotifyPropertyChanged) a nézetmodellben helyet kap a változásfigyelő gyűjtemény (ObservableCollection), és annak feltöltése

3. feladat Módosítsuk az előző alkalmazást úgy, hogy lehessen felvenni új hallgatót. a felületen három szövegdobozban megadhatjuk a hallgató adatait, majd egy gomb segítségével felvehetjük őket az alkalmazásba ehhez létrehozunk egy új parancs osztályt, amely a hallgató felvételét végzi (StudentAddCommand), és a végrehajtáskor felveszi a listába az új hallgatót a parancsot tulajdonságként felvesszük a nézetmodellben magát az új hallgatót (NewStudent) is felvesszük a nézetmodellben, hogy lehessen mihez kötni a felületi adatokat