Wzorzec Model-View-ViewModel jest najczęściej wykorzystywany przez programistów WPF. Związane jest to z mechanizmem wiązań, który znacząca ułatwia wdrożenie MVVM do projektu. ViewModel stanowi wyeksponowany model przeznaczony do bindingu, z kolei widok to zwykły, pasywny plik XAML. Ważną cechą ViewModel jest brak powiązań z interfejsem użytkownika. Najlepiej aby projekt zawierający ViewModel nie posiadał żadnych referencji do bibliotek warstwy prezentacji.
Częstym zadawanym pytaniem jest: Jak wywoływać standardowe okna komunikatów (MessageBox)? Aby poprawnie zaimplementować VM, nie powinno się wywoływać komunikatów bezpośrednio VM. Umieszczenie wywołań w Code-Behind również nie jest dobrym podejściem (często messagebox zależą od logiki biznesowej oraz nie powinniśmy umieszczać kodu w code-behind).
Najlepszym rozwiązaniem jest stworzenie usługi odpowiedzialnej za wyświetlanie komunikatów a następnie załadowanie jej z kontenera. Interfejs reprezentujący takową usługę mógłby wyglądać następująco:
interface IMessageBoxService { Result Show(string message); }
Z kolei przykładowe implementacje:
class RealMessageBoxService: IMessageBoxService { public Result Show(string message) { MessageBox.Show(message); return Result.OK // w tym miejscu powinnismy zmapowac wynik zwrocony przez MessageBox do wlasnego enum. } } class MockBoxService: IMessageBoxService { public Result Show(string message) { return Result.OK; } }
Następnie w ViewModel powinniśmy skorzystać z kontenera (IoC, np. UnityContainer) aby uzyskać instancję usługi:
IMessageBoxService service = container.Resolve<IMessageBoxService>();
Dzięki wstrzyknięciu zależności, możemy w łatwy sposób przełączać się między prawdziwą implementacją wyświetlającą komunikat a zwykłym stubem. Podsumowując z przedstawionego w tym poście podejścia zyskujemy:
-
Niezależność od bibliotek warstwy prezentacji (System.Windows itp.)
-
TESTOWALNOŚĆ – wyświetlając komunikaty bezpośrednio w VM pozbawieni jesteśmy możliwości skorzystania z testów jednostkowych (testy jednostkowe wymagające interakcji użytkownika?- zaprzeczenie głównym zasadom). W przypadku usług, możemy wstrzyknąć zwykły MOCK object i przetestować kod – nawet w przypadku skomplikowanych worflow’ów w których logika biznesowa zależy od interakcji użytkownika.
-
Jedno miejsce w kodzie w którym można umieszczać metody odpowiedzialne za wyświetlanie najpopularniejszych okien dialogowych. W końcu można stworzyć dodatkowe metody typu ShowWelcomeText itp. w klasie implementującej usługę.
Cześć!
Temat dla mnie bardzo na czasie. Proszę załącz przykładowe kompletne źródła, wystarczy programik typu “Hello Word!”
Pozdrawiam
Grzesiek