Choć domyślnie aplikacje WPF piszemy z wykorzystaniem code-behind, to nie ma technologicznych przeciwwskazań do zastosowania w tym przypadku wzorca MV

Choć domyślnie aplikacje WPF piszemy z wykorzystaniem code-behind, to nie ma technologicznych przeciwwskazań do zastosowania w tym przypadku wzorca MVVM, do którego ta technologia jest również częściowo przystosowana. Tak naprawdę największa zmiana musi zajść w naszych głowach — musimy zmodyfikować podejście do tego, w jaki sposób projektujemy poszczególne elementy aplikacji.  

 

Tworząc kontrolery podpinane później na UI, nie powinniśmy w ogóle myśleć o interfejsie graficznym. Kontroler powinien wystawiać odpowiednie modele oraz komendy, które później zostaną skonsumowane w widoku. Jest to spora zmiana w stosunku do klasycznego podejścia, w którym to w miejscu code-behind możemy zrobić dosłownie wszystko, niczym się nie przejmując.  

 

Na szczęście trudności związane z przejściem na MVVM można sobie częściowo złagodzić. Wystarczy sięgnąć po gotową bibliotekę (w myśl zasady „nie wymyślaj koła od nowa”), np. po mój ulubiony MVVM Light.  

 

NuGet

Biblioteka, jak większość rozwiązań w dzisiejszych czasach, jest dostępna na NuGecie i w wersji „libs” można ją pobrać stąd. Dostępna jest również wersja pełna, która po instalacji dodaje kilka standardowych elementów do naszego projektu. Na potrzeby przykładu zdecydowałem się skorzystać z pierwszej wersji paczki, by mieć większą kontrolę nad wszystkimi elementami tej układanki.  

 

Przykład praktyczny

Przykład należy rozpocząć od utworzenia nowego projektu typu Wpf Application. W kolejnym kroku powinniśmy zainstalować wspomnianą w punkcie wyżej paczkę MvvmLightLibs.  

 

W kolejnych krokach dodajemy poszczególne elementy do projektu.

Zaczynamy od folderu ViewModels, w którym pojawi się przykładowy ViewModel, a także klasa ViewModelLocator, która w MvvmLight jest domyślnie używana do wyciągania ViewModeli na UI.  

 

 

 MainViewModel: using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using System; using System.Windows.Input; namespace MvvmLightSampleWPFProject.ViewModels { public class MainViewModel ViewModelBase { private Guid data; public MainViewModel() { this.LoadDataCommand = new RelayCommand(() => { this.Data = Guid.NewGuid(); }); } public ICommand LoadDataCommand { get; private set; } public Guid Data { get { return this.data; } set { this.data = value; this.RaisePropertyChanged("Data"); } } } } 

 

 

 

To bardzo prosty ViewModel, ale warto zwrócić uwagę na kilka rzeczy:

  • ViewModel dziedziczy z klasy ViewModelBase wprowadzonej przez MvvmLight.
  • Obsługa interfejsu INotifyPropertyChanged odbywa się w klasie ViewModelBase (dokładnie w klasie ObservableObject, która jest bazą dla wyżej wspomnianej). Użytkownik dostaje do dyspozycji metodę RaisePropertyChanged.
  • Do obsługi komendy wykorzystałem standardową implementację RelayCommand.

 

Nasz świeżo upieczony utworzony ViewModel powinniśmy „zarejestrować” w ViewModelLocatorze, którego kod znajdziecie poniżej:  

 

 

 using GalaSoft.MvvmLight.Ioc; using Microsoft.Practices.ServiceLocation; namespace MvvmLightSampleWPFProject.ViewModels { public class ViewModelLocator { public ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Register(); } public MainViewModel MainViewModel { get { return ServiceLocator.Current.GetInstance(); } } } } 

 

 

 

Oczywiście jest to błahe rozwiązanie. W rzeczywistym projekcie możemy pokusić się np. o zastosowanie refleksji do automatycznej rejestracji ViewModeli. Z powodzeniem wykorzystałem takie rozwiązanie w kilku projektach.  

 

Mając ViewModel i Locator, możemy dokonać rejestracji tego drugiego w pliku App.xaml. Dzięki temu będziemy mieli dostęp do Locatora w całej aplikacji. Poniżej kod zmodyfikowanego pliku App.xaml:  

 

      

 

 

 

Ostatnim elementem wdrożenia jest przykładowy Window. Do standardowo dodanego MainWindow.xaml (URI do niego znajduje się na listingu powyżej) wrzuciłem następującą zawartość (część XAML):   

 

Za pomocą Locatora, ustawiam DataContext na MainViewModel. W głównym StackPanelu umieszczam zaś dwa elementy:

 

  • Button, który binduje się do komendy LoadDataCommand,
  • TextBlock, który wyświetla efekt działania powyższej komendy.

 

To tyle. Jest to w pełni działająca aplikacja wykorzystująca wzorzec MVVM Light. Ponieważ przykład był bardzo prosty, praktycznie pominąłem model. Pole Data zostało wtłoczone bezpośrednio do klasy ViewModel.  

 

Pełny kod projektu znajdziecie na Githubie.      

Jerzy Piechowiak

Altcontroldelete.pl

 


Szukasz informacji? Kliknij poniżej: