mvvmcross: NavigationService.Navigate хвърля MvxException Не може да намери входящ mvxviewmodelrequest

В моето приложение WP8 имам MainView, препращащ към MainViewModel. MainView е меню, където потребителите могат да навигират до други изгледи, за да изпълнят някои задачи. Навигирането от MainView работи перфектно, тъй като използвам ShowViewModel. Обаче навигирането от други изгледи, когато потребителят завърши задача, обратно към MainView с помощта на NavigationService.Navigate(URI) хвърля изключение „Не може да се намери входящ mvxviewmodelrequest“.

За да избегна това изключение, конструирах URI като по-долу

var req = "{\"ViewModelType\":\"MyApp.Core.ViewModels.MainViewModel, MyApp.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\",\"ClearTop\":\"true\",\"ParameterValues\":null,\"RequestedBy\":null}";
NavigationService.Navigate(new Uri("/MainView.xaml?ApplicationUrl=" + Uri.EscapeDataString(req), UriKind.Relative));

Някой има ли по-добър начин за използване на NavigationService.Navigate?


person vbn    schedule 09.01.2014    source източник


Отговори (1)


Повечето навигации в образците на MvvmCross се инициират или от MvxAppStart обекти, или от MvxViewModels. И двата класа наследяват от MvxNavigatingObject и използват методите ShowViewModel, изложени там - вижте https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNavigatingObject.cs

От MvxNavigatingObject можете да видите, че MvvmCross насочва извикването за навигация към IMvxViewDispatcher, което в WindowsPhone е много тънък обект - всичко, което прави, е да маршалира всички извиквания към нишката на потребителския интерфейс и да ги предаде на IMvxViewPresenter - вижте https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxPhoneViewDispatcher.cs

Презентаторът е обект, създаден в Setup - и изпълнението по подразбиране използва IMvxPhoneViewModelRequestTranslator за преобразуване на навигационното извикване в навигация, базирана на uri - вижте https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxPhoneViewPresenter.cs

След това Silverlight/WindowsPhone използва този uri за навигация, създава необходимата Xaml страница и след това извиква OnNavigatedTo на тази страница. Като част от base.OnNavigatedTo(); предаване на MvxPhonePage, MvvmCross след това извиква метода за разширение OnViewCreated. Този метод проверява дали вече има ViewModel - ако няма такъв, той се опитва да намери такъв, като използва информацията в uri - вижте https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxPhoneExtensionMethods.cs


Имайки предвид това обяснение, ако някое приложение някога поиска да инициира MvvmCross навигация от клас, който все още не е наследил от MvxNavigatingObject - напр. от някой Service или от някакъв друг клас, тогава има няколко опции:

  1. Можете да предоставите shim обект за извършване на навигацията - напр.:

     public class MyNavigator : MvxNavigatingObject {
          public void DoIt() {
              ShowViewModel<MyViewModel>();
          }
     }
    
     // used as:
     var m = new MyNavigator();
     m.DoIt();
    
  2. Вместо това можете да използвате IoC, за да намерите IMvxViewDispatcher или IMvxViewPresenter и да извикате техните Show методи директно

     var request = MvxViewModelRequest<MyViewModel>.GetDefaultRequest();
     var presenter = Mvx.Resolve<IMvxViewPresenter>();
     presenter.Show(request);
    
  3. Можете да напишете ръчен код, който имитира това, което IMvxViewPresenter прави - точно както имате във вашия код - въпреки че може да е "по-безопасно" да използвате IMvxPhoneViewModelRequestTranslator.cs за подпомагане при генерирането на url - вижте person Stuart    schedule 10.01.2014