2016-10-26 4 views
1

Ich arbeite an einem Konflikt zwischen Prism.Forms (v6.2.0) und dem Xamarin Messaging Plugin (Xam.Plugins.Messaging v3.2.1), wenn ich versuche, eine E-Mail von meiner App zu senden.Wie Prism für Xamarin.Forms (Ansicht) Navigationsstapel zurücksetzen?

Der folgende Code - von einem meiner Viewmodels ausgeführt:

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); 
} 

Erzeugt diesen Fehler - und die E-Mail-zu-gesandt werden nie auf dem Bildschirm erscheint:

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

I Ich glaube, dass dies passiert, weil der iOS-spezifische Teil des Messaging-Plugins über eine .GetVisibleViewController()-Methode verfügt, die nach einem UIViewController mit einer sichtbaren Ansicht sucht, um die zu sendende E-Mail anzuzeigen; und es ist ein View-Controller, den iOS nicht mag.

Ich möchte darauf hinweisen, dass ich fast identischen Code (zu dem oben gezeigten) ohne Probleme in einer MVVM-gemusterten Xamarin.Forms App, die nicht Prism.Forms verwendet [Bearbeiten: Brian L. macht den folgenden Punkt dass dieses Problem wahrscheinlich nicht von Prism verursacht wird, und ich tendiere dazu, ihm zuzustimmen; es ist eher mit kleinen Unterschieden im "Navigationsfluss" zwischen den beiden Apps verbunden, obwohl der E-Mail-Aufbau-/Sendecode derselbe ist]. Wenn die Zeile MessagingPlugin.EmailMessenger.SendEmail(email); ausgeführt wird, sollte auf dem Bildschirm eine E-Mail mit Empfänger, Betreff und Nachricht angezeigt werden (siehe Code). und mit den Schaltflächen Senden oder Abbrechen. Dies funktioniert in der nicht-Prism Xamarin.Forms App.

Also, ich habe dieses Problem genug um den .SendEmail(email) Methodenaufruf arbeiten ordnungsgemäß funktioniert. Ich muss meine X.F-Seite (d. H. Die Ansicht für mein Ansichtsmodell) an den iOS-spezifischen Projektcode übergeben, um .CreateViewController() darauf anzurufen. Ich erstelle eine UIWindow mit diesem neuen UIViewController als RootViewController, und mache dann dieses Fenster .MakeKeyAndVisible(). Ich habe den Code von Xam.Plugins.Messaging so optimiert, dass ich einen UIViewController zur Verwendung übergeben kann. Nachdem der Methodenaufruf .SendEmail(email) passiert ist, entsorge ich mein neu erstelltes UIWindow; so dass ich es nicht sehe, nachdem die E-Mail gesendet oder storniert wurde.

Dies alles funktioniert und ermöglicht es mir, die E-Mail-Versandfunktionen des Messaging-Plug-Ins wie erwartet zu verwenden.

Mein einziges verbleibendes Problem besteht darin, dass Navigationsaufrufe an meine ursprüngliche navigationService-Instanz von ViewModel (d. H. Das ViewModel, das versucht hat, die E-Mail mit dem obigen Code zu senden) fehlschlagen, nachdem die E-Mail gesendet wurde. Andere Funktionen in meinem view/viewmodel funktionieren nach dem Senden der E-Mail einwandfrei. sondern ruft navigationService.GoBackAsync() oder navigationService.NavigateAsync() fehlschlagen und einen vertrauten Fehler erzeugen:

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!

Ich glaube, dass das, was soll ich tun, um meinen Prism Navigation (Ansicht) Stapel, mit so etwas wie diesem (Code für Xamarin.Forms zurückgesetzt, ohne Prism):

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

Aber ich weiß nicht, einen Weg zu tun „Navigationsstapel zu verändern Operationen“ wie das mit dem Prism Navigation sehen. Aber vielleicht jemand anderes?

Vielen Dank im Voraus ...

Antwort

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

Fast identisch sind, ist nicht identisch. Ich möchte erwähnen, dass Prism in Bezug auf MVVM nichts besonderes tut. Es legt einfach den Page.BindingContext für Sie fest. Das ist es. Wenn Sie also nur mit einer Ansicht und einer VM in einer App ohne Prism arbeiten, gibt es keinen Unterschied zwischen der Verwendung von Prism.

Um Ihre Frage zu beantworten, verwenden Sie einfach einen absoluten URI, um den Navigationsstapel zurückzusetzen.

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

Dies zu MainPage = new NavigationPage(new MainPage()); entspricht

+0

Danke Brian, wird dieser versuchen! –

+0

Danke nochmal, Brian. Das hat mein Problem behoben. Anstatt "navigationService.NavigateAsync (" HomePage ")" aufzurufen, rufe ich jetzt 'navigationService.NavigateAsync (" app: /// HomePage ")' auf - und alles funktioniert einwandfrei. Ich suchte nach Dokumentation über absolute Prism-URIs und es war mir nicht klar, ob "myapp" in obigem Beispiel eine "magische Zeichenfolge" war - oder für meine App angepasst werden musste. Aber es scheint, dass es "anystring: /// HomePage" sein kann und immer noch funktioniert. Lass es mich wissen, wenn das falsch ist. Falls das zukünftigen Lesern dieser Frage/Antwort hilft ... –

+1

Das ist korrekt. Im Wesentlichen benötigen Sie lediglich einen gültigen absoluten URI. Was kann alles von "http: // www.myapp.com/MainPage" sein, um eine tatsächliche 'neue Uri (" einige Uri ", UriKind.Abslute)' –

Verwandte Themen