2016-10-26 2 views
1

Я работаю над конфликтом между Prism.Forms (v6.2.0) и плагином сообщений Xamarin (Xam.Plugins.Messaging v3.2.1) при попытке отправить электронное письмо из моего приложения.Как сбросить призму для Xamarin.Forms (просмотреть) навигационный стек?

Следующий код - выполнен из одного из моих ViewModels:

using Plugin.Messaging; 

if (MessagingPlugin.EmailMessenger.CanSendEmail) 
{ 
    var email = new EmailMessageBuilder() 
     .To("[email protected]") 
     .Subject("Email subject here!") 
     .Body("Dear friend,\nI would like to say...\n\n\n") 
     .Build(); 
    MessagingPlugin.EmailMessenger.SendEmail(email); 
} 

Производит эту ошибку - и электронная почта к не быть посланным не появляется на экране:

Warning: Attempt to present <MFMailComposeViewController: 0x108fb4400> on <Xamarin_Forms_Platform_iOS_PageRenderer: 0x107de67c0> whose view is not in the window hierarchy!

I что это происходит из-за того, что часть iOS-части плагина Messaging имеет метод .GetVisibleViewController(), который ищет UIViewController с видимым видом для отображения отправляемого письма; и он ищет контроллер вида, который не нравится iOS.

Я хочу указать, что у меня есть почти идентичный код (к показанному выше), работающий без проблем в приложении Xamarin.Forms с шаблоном MVVM, которое не использует Prism.Forms [edit: Brian L. делает следующий пункт что эта проблема, вероятно, не вызвана Призмом, и я склонен согласиться с ним; это скорее связано с незначительными различиями в «потоке навигации» между этими двумя приложениями, хотя код создания электронной почты/отправки одинаковый]. Когда выполняется линия MessagingPlugin.EmailMessenger.SendEmail(email);, на экране появляется сообщение электронной почты: Получатель, Тема и Тело, как показано в коде; и с помощью кнопок «Отправить» или «Отмена». Это отлично работает в приложении non-Prism Xamarin.Forms.

Итак, я справился с этой проблемой достаточно, чтобы вызов метода .SendEmail(email) работал правильно. Мне нужно передать мою страницу X.F (т. Е. Представление для моей модели просмотра) в код проекта, специфичный для iOS, для вызова на нем .CreateViewController(). Я создаю UIWindow с этим новым UIViewController как свой RootViewController, а затем создаю это окно .MakeKeyAndVisible(). Я изменил код Xam.Plugins.Messaging, чтобы позволить мне пройти в UIViewController для использования. После вызова метода .SendEmail(email) я удаляю свой вновь созданный интерфейс UIWindow; так что я не вижу его после отправки или отмены электронной почты.

Все это работает и позволяет мне использовать возможности отправки электронной почты подключаемого модуля, как и ожидалось.

Моя единственная оставшаяся проблема заключается в том, что навигация вызывает мой экземпляр navigationService моего первоначального ViewModel (т. Е. ViewModel, который пытался отправить электронное письмо, используя код выше), все сбой после отправки сообщения электронной почты. Другие функции на моем представлении/режиме просмотра отлично работают после отправки электронного письма; но призывает к navigationService.GoBackAsync() или navigationService.NavigateAsync() неудачу и производят знакомый ошибку:

Warning: Attempt to present <Xamarin_Forms_Platform_iOS_ModalWrapper: 0x1359c21a0> on <Xamarin_Forms_Platform_iOS_PlatformRenderer: 0x133df9640> whose view is not in the window hierarchy!

Я считаю, что то, что я хочу сделать, это вернуть мой Prism NavigationService (вид) стек, с чем-то вроде этого (код для Xamarin.Forms, без Призма):

Navigation.InsertPageBefore(new HomePage(), Navigation.NavigationStack.First()); 
Navigation.PopToRootAsync(true); 

Но я не вижу способ сделать «навигационный стек изменения операций», как, что с Prism NavigationService. Но может быть, кто-то другой?

Спасибо заранее ...

ответ

8

I have almost identical code (to that shown above) running without problems in an MVVM-patterned Xamarin.Forms app that does not use Prism.Forms

Почти одинаковые, не идентичны. Я хотел бы упомянуть, что Prism не делает ничего особенного в отношении MVVM. Он просто устанавливает для вас PageBindingContext. Вот и все. Поэтому, если вы работаете с только View и VM в приложении без Prism, нет никакой разницы между использованием Prism.

Чтобы ответить на ваш вопрос, чтобы сбросить стек навигации, вы просто используете абсолютный URI.

NavigateAsync("myapp:///NavigationPage/MainPage")

Это эквивалентно MainPage = new NavigationPage(new MainPage());

+0

Спасибо Брайану, будет пытаться это! –

+0

Еще раз спасибо, Брайан. Это исправило мою проблему. Вместо вызова 'navigationService.NavigateAsync (« HomePage »), я теперь вызываю' navigationService.NavigateAsync («app: /// HomePage») '- и все работает правильно. Я искал документацию о Prism Absolute URI, и мне было непонятно, если «myapp» в вашем примере выше был «волшебной строкой» - или должен был быть настроен для моего приложения. Но похоже, что это может быть «anystring: /// HomePage» и все еще работает. Дайте мне знать, если это неправильно. В случае, если это поможет будущим читателям этого вопроса/ответа ... –

+1

Правильно. По сути, все, что вам нужно, это предоставить действительный абсолютный URI. Что может быть что угодно: от http: // www.myapp.com/MainPage, до создания фактического 'нового Uri (« некоторый uri », UriKind.Abslute)' –