Nawigacja między widokami

W aplikacji POS możemy otwierać dowolną liczbę widoków w różnych trybach (widoku podstawowego, modalnego lub komunikatu), przy czym w danej chwili aktywny może być tylko jeden z każdej grupy. Pozostałe otwarte określone są mianem nieaktywnych. W każdym momencie będąc na dowolnym widoku podstawowym możemy wywołać okno przełączania pomiędzy widokami podstawowymi (menu nawigacji), w celu aktywowania wybranego innego widoku, który został wcześniej otwarty i nie został zamknięty (stał się nieaktywny). Menu nawigacji nie możemy wywołać na widoku modalnym ani na widoku komunikatu.

Menu nawigacji

Menu nawigacji wywołać możemy za pomocą skrótu klawiszowego CTRL+TAB lub za pomocą przycisku  widocznego w sekcji statusowej obok zegara. W oknie tym otwarte widoki podstawowe reprezentowane są w postaci różnokolorowych kafli z tytułem, ikoną i/lub dodatkowym opisem. Tytuł kafla ustawić możemy za pomocą właściwości Header w klasie View lub za pomocą właściwości SwitchHeader na viewmodelu (jeżeli chcemy żeby różnił się od nagłówka widoku). Ikonę oraz kolor ustawiamy za pomocą styli w pliku ModernUI.xaml. Ustawienie koloru i ikony wykonywane jest w dokładnie taki sam sposób jak podczas definiowania koloru i ikony dla rejestrowanego kafla w menu głównym. Dlatego, jeżeli widok został zarejestrowany już w menu głównym to kafel w oknie menu nawigacji przyjmie kolor i ikonę taką jak kafel w menu głównym pod warunkiem, że wartość klucza resourcesów (pierwszy argument) użyta w metodzie RegisterMenuTile jest taka sama jak wartość właściwości HeaderLayoutId w code-behind widoku. W naszym przypadku nazwy się różnią dlatego wymagane będzie dodanie dodatkowych wpisów w ModernUI.xaml.

Definiowanie w ModerUI.xaml koloru i ikony kafla w oknie menu nawigacji dla przykładowego widoku OrdersView:

 

<SolidColorBrush x:Key="OrdersViewId.Default.Background" Color="Red" />
<models:ImageKey x:Key="OrdersViewId.Default.ImageKey" SvgValue="ListIcon" />

 

Należy pamiętać, że w powyższym przypadku OrdersViewId to wartość przypisana do HeaderLayoutId w klasie widoku.

Dodatkowo, istnieje możliwość dodania w kaflu dodatkowego opisu (tak jak to widać na kaflu Nowe zamówienie na powyższym zrzucie ekranu). Za ten tekst odpowiada właściwość SwitchHeader2 w klasie view-modelu.

Otwieranie widoków

Widoki możemy otwierać w kilku trybach (jako widok podstawowy, widok modalny lub też widok komunikatu). Możemy sterować czy dany widok ma zostać otwarty jako niezależny od innych widoków (oddzielna pozycja w oknie menu nawigacji), czy ma być potomkiem obecnie aktywnego (brak nowej pozycji w menu nawigacji). Otwierając widok możemy ustawić parametr IsPreviewMode (otwiera widok w trybie tylko do odczytu, większość kontrolek jest automatycznie blokowana do edycji) oraz dowolną liczbę własnych parametrów.

Widoki możemy otwierać za pomocą metod dostępnych w klasie ViewModelBase oraz w serwisie IViewManager. Najprostszym sposobem otwarcia widoku podstawowego jest wywołanie metody OpenView<TView>(), gdzie TView to nazwa klasy widoku, który chcemy otworzyć lub aktywować, jeżeli już jest otwarty. Dodatkowe parametry:

  • isChild (bool) – parametr określający czy otwierany widok ma być potomkiem aktualnie aktywnego,
  • parameters (NavigationParameters) – parametr pozwalający na przekazania dowolnej liczby własnych parametrów do viewmodelu otwieranego widoku,
  • isPreviewMode (bool) – parametr, który dostępny jest już w konstruktorze viewmodelu otwieranego widoku (w przeciwieństwie do parameters, który dostępny jest dopiero w metodach inicjalizacyjnych viewmodelu, o których więcej tutaj Kolejność wywołań metod ViewModelu podczas nawigacji). Parametr służy do otwierania widoku w trybie podglądu (z ograniczoną funkcjonalnością). Ustawienie tego parametru na true spowoduje ustawienie właściwości tylko do odczytu IsPreviewMode w klasie ViewModelBase. Dodatkowo, kontrolki TextBox, SwitchBox, RadioButton, NumericTextBox, ComboBox, CheckBox z przestrzeni Comarch.POS.Presentation.Core przejdą w tryb tylko do odczytu, jeżeli tylko któraś z nich znajdzie się w tym widoku.

Aby otworzyć widok w trybie widoku modalnego należy skorzystać z metody:

OpenModalView<TView>(), gdzie TView to nazwa klasy widoku, który chcemy otworzyć lub aktywować, jeżeli jest już otwarty. Dodatkowe parametry:

  • parameters (NavigationParameters) – analogicznie jak dla OpenView
  • isPreviewMode (bool) – analogicznie jak dla OpenView

Metoda nie posiada parametru isChild, ponieważ wszystkie widoki modalne otwierane są w trybie hierarchicznym (są potomkiem widoku, który go otworzył). Wyjątkiem jest brak relacji pomiędzy różnymi typami widoków. Przykładowo otwierając widok modalny z aktywnego widok podstawowego nie zostanie utworzona zależność parent-child.

W celu otwarcia widoku w trybie widoku komunikatu należy wykonać dwa kroki. Pierwszy z nich to ustawienie w xamlu widoku wyrównania poziomego:

<core:View x:Class="Comarch.POS.Presentation.Sales.Views.OrdersView"
                      HorizontalAlignment="Stretch"
…

 

Natomiast drugi to wywołanie metody:

OpenMessageView<TView>(), dostępnej tylko w serwisie ViewManager, gdzie TView to nazwa klasy widoku, który chcemy otworzyć. Analogicznie jak dla widoku modalnego, relacja parent-child występuje zawsze z pominięciem relacji pomiędzy różnymi typami widków. Dodatkowe parametry:

  • parameters (NavigationParameters) – analogicznie jak dla OpenView i OpenModalView,
  • isPreviewMode (bool) – analogicznie jak dla OpenView I OpenModalView

Jeżeli chcemy tylko wyświetlić prosty komunikat lub pytanie z dowolnymi przyciskami, wystarczy, że skorzystamy z serwisu MonitService. Dostępne tam są metody takie jak:

  • ShowInformation – metoda wyświetlająca widok komunikat z dowolną treścią oraz przyciskiem OK,
  • ShowError – metoda wyświetlając widok komunikatu z treścią wyjątku i przyciskiem OK,
  • ShowQuestion – metoda wyświetlająca widok komunikatu dowolną treścią oraz z przyciskami decyzyjnymi TAK i NIE,
  • Show – metoda wyświetlająca widok komunikatu z dowolną treścią oraz dowolnymi przyciskami akcji predefiniowanymi OK, TAK/NIE) lub dowolną liczbą własnych przycisków.

Więcej na temat komunikatów w artykule Notyfikacje i Komunikaty.

Zamykanie widoków

W przypadku zamykania widoków, mamy do dyspozycji metody pozwalające na zamykanie aktualnie aktywnego widoku, metodę do zamykania wybranego widoku (z opcją zamknięcia również wszystkich jego przodków). Zamykając widok możemy, analogicznie jak w przypadku otwierania, dodać dodatkowe własne parametry, które zostaną przekazane do widoku, który zostanie aktywowany po zamknięciu obecnego.

Zamykając aktywny widok, zawsze zostanie aktywowany widok, z którego zamykany widok został wcześniej otwarty. W przypadku, gdy widoki są w relacji rodzic-dziecko (podczas otwieranie widoku IsChild=true), zamykając widok dziecka powrócimy do widoku rodzica.

Aby zamknąć aktywny widok należy użyć z metody:

Będąc na viewmodelu należy wywołać metodę Close(), która bezpośrednio wywołuje metodę CloseView w ViewManagerze przekazując swój widok jako parametr. Metoda Close zamyka zawsze widok powiązany z aktualnym viewmodelem. Dodatkowe parametry:

  • parameters (NavigationParameters) – parametr pozwalający na przekazanie informacji z zamykanego widoku do widoku, który zostanie aktywowany

 Aby zamknąć wskazany widok (aktywny lub nieaktywny) należy użyć metody:

CloseView(), znajdującej się w serwisie IViewManager. Dodatkowe parametry metody:

  • view (IView) – parametr określający jaki widok ma zostać zamknięty,
  • closeParents (bool) – parametr definiujący czy zamknąć również wszystkie widoki zależne w relacji rodzic-dziecko (widoki otwierane z parametrem IsChild=true). Domyślnie wartość ustawiona na true.

Kolejność wywołań metod nawigacyjnych

Podczas nawigacji pomiędzy widokami (otwieranie, zamykanie, przełączania aktywnego widoku) wywoływane są specjalne metody w view-modelach biorących udział w nawigacji. Metody te pozwalają na wykonanie odpowiednich akcji w zależności od tego czy widok jest otwierany po raz pierwszy, aktywowany ponownie, deaktywowany, czy też zamknięty. Dostarczają również parametry, które wysyłamy podczas wywoływania metod otwierających oraz zamykających.

Metody nawigacyjne dostarcza klasa bazowa każdego viewmodelu – ViewModelBase. Są nimi metody OnInitialization, OnActivation, OnActivated, OnDeactivted, Dispose oraz IsTarget. Odpowiednie metody są automatycznie wywoływane podczas procesu otwierania zarówno na widoku, z którego otwieramy nowy, jak i na docelowym. W przypadku procesu zamykania określone metody są wywoływane na zamykanym widoku oraz na widoku, który zostanie aktywowany w wyniku zamknięcia obecnego. Tak samo w przypadku przełączania się pomiędzy otwartymi widokami. Istotną kwestią jest to jakie metody wywoływane są podczas określonej nawigacji oraz ich kolejność.

Proces otwierania, zamykania i przełączania między widokami obrazuje poniższy diagram:

Opis metod:

  • IsTarget (ViewModelBase)

Wywoływana jest podczas otwierania widoku, przed konstruktorem widoku, na wszystkich instancjach viewmodeli widoków zgodnych typem z otwieranym. Jeżeli nie istnieje żadna instancja widoku typu otwieranego to zostanie utworzony nowy widok. Jeżeli istnieją już otwarte widoki tego typu, metoda będzie wywoływać się na każdym viewmodelu widoku w kolejności ich otwarcia. Jeżeli których z nich wróci true to zostanie aktywowany. Jeżeli natomiast żaden istniejący widok tego typu nie wróci true, wtedy zostanie utworzona nowa instancja.

  • OnInitialization (ViewModelBase)

wywoływana jest w ViewModelu tylko podczas otwierania nowego widoku (nowa instancja, nowa zakładka). Brak dostępu do rodzica (wywołanie ViewManager.GetParentViewModel(this) zwróci null).
Uwaga: w tej metodzie nie należy otwierać ani zamykać widoków!

  • OnActivation (ViewModelBase)

wywoływana jest podczas każdego otwarcia widoku czy też samej aktywacji. Brak dostępu do rodzica (wywołanie ViewManager.GetParentViewModel(this) zwróci null).
Uwaga: w tej metodzie nie należy otwierać ani zamykać widoków!

  • OnActivated (ViewModelBase)

wywoływana jest podczas każdego otwarcia widoku czy też samej aktywacji.

  • OnDeactivated (ViewModelBase)

wywoływana jest podczas deaktywacji lub zamknięcia widoku.

  • Dispose (ViewModelBase)

wywoływana jest tylko podczas zamykania widoku. Pozwala na zwolnienie zasobów niezarządzalnych przez Garbage Collector lub zatrzymanie wątków potomnych.

  • OnApplyViewTemplate (View)

Wywoływana w code-behind klasy widoku, jednorazowo po utworzeniu instancji widoku i po załadowaniu wszystkich składowych (kontrolek) widoku.

Czy ten artykuł był pomocny?