2014-02-20 14 views
5

Ich habe vor kurzem einen benutzerdefinierten UriMapper zum Speichern von Dateien in meinem isolierten Anwendungsspeicher hinzugefügt, wenn Sie sie aus IE öffnen. Der Code dafür sieht wie folgt aus:Windows Phone App ruft MapUri() zweimal auf, wenn ich NavigateService.Navigate() anrufe

class AssociationUriMapper : UriMapperBase 
{ 
    public override Uri MapUri(Uri uri) 
    { 
     var tempUri = uri.ToString(); 

     if (tempUri.Contains("/FileTypeAssociation")) 
     {     
      int fileIdIndex = tempUri.IndexOf("fileToken=") + 10; 
      string fileId = tempUri.Substring(fileIdIndex); 

      SaveFileToIsolatedStorage(fileId); 

      return new Uri("/MainPage.xaml", UriKind.Relative);     
     } 

     return uri; 
    } 
} 

In InitializePhoneApplication() ich tun

RootFrame.UriMapper = new AssociationUriMapper(); 

Und natürlich habe ich hinzugefügt, um die Extensions Tag WMAppManifest.xml

All dies funktioniert gut ... aber ich bemerkte ein seltsames Verhalten. Ich erhalte jedes Mal zwei Kopien der Dateien, wenn ich sie von IE öffne. Wenn ich einen Breakpoint in mein überschriebenes MapUri setze, wird es jedes Mal zweimal gedrückt, wenn die Anwendung von IE automatisch gestartet wird.

Als ich begann, dies weiter zu untersuchen, bemerkte ich, dass dies passiert, wenn ich NavigateService.Navigate() aufrufen. Aber nicht wenn ich anrufe NavigateService.GoBack.

Weiß jemand, warum das passiert? Warum werden MapUri() zweimal aufgerufen, wenn Navigate() heißt? Tritt etwas auf, wenn eine neue Instanz einer Seite erstellt wird? (Ich habe festgestellt, dass beim Aufruf Navigate() eine neue Instanz der aufgerufenen Seite erstellt wird, aber wenn wir GoBack() rufen wir die bereits erstellte Instanz der Seite, die wir navigiert haben).

Edit:
ich jetzt einen kleinen Test-Anwendung von Grund auf neu gemacht habe. Das Ergebnis ist das gleiche. Wenn ich eine Klasse, die von UriMapperBase erbt und überschreibt die MapUri Methode, MapUri wird zweimal aufgerufen, wenn ich auf die Anwendung navigieren oder NavigateService.Navigate() in der Anwendung aufrufen.

Die offensichtliche Problemumgehung für mein Problem ist natürlich, eine separate Seite zu haben, die die Anwendung navigiert und die Seite SaveFileToIsolatedStorage() aufrufen. Aber das beantwortet immer noch nicht die Frage, warum das Verhalten so ist wie es ist.

+0

Ich habe das gleiche Problem und es ist wirklich nervig für das Verhalten meiner App –

+0

Ja.Es ist sehr seltsam. Es hat definitiv etwas damit zu tun, wie Dinge beim Erstellen eines neuen Objekts auf einer Seite aufgerufen werden. Irgendein Umlauf, der MapUri() zweimal aufruft. Können Sie Ihre Logik trotzdem von der MapUri() Methode wegbewegen? Wenn Sie Ihre Logik in OnNavigatedTo() in einer separaten Ansicht ausführen, ohne Initialize() im Konstruktor aufzurufen und dann zurück zu der Seite zu navigieren, die Sie anzeigen möchten, wird die Logik nur einmal ausgeführt, und der Benutzer sieht die Seite nicht Navigiere zu, da du es nicht initialisierst. So habe ich mein Problem gelöst. – zmurf

+0

Vielen Dank für den Tipp, es könnte nützlich sein –

Antwort

3

Versuchen Sie, den UriMapper über das XAML der MainPage mit einem ViewModel statt durch Code zu verbinden.

+0

Guter Tipp. Werde das versuchen. – zmurf

+0

Können Sie mich auf einen Link verweisen, der erklärt, was das bedeutet und wie man es versucht? – Shawn

0

Einige Cheat in meinem Code, nur ein Ereignis zu halten.

private static string lockUri = ""; 

    public override Uri MapUri(Uri uri) 
    { 
     lock (lockUri) 
     { 
      if (lockUri != uri.ToString()) 
      { 
       lockUri = uri.ToString(); 
       return null; 
      } 
     } 

     // Your code to route here 
    } 
+0

warum sperren? Immer im UI-Thread laufen. – Cologler

0

das ist, was ich tue:

public class AppUriMapper : UriMapperBase 
{ 
    public static bool IsNavigating = false; 

    public override Uri MapUri(Uri uri) 
    { 
     var endUri = uri; 

     if (IsNavigating) 
     { 
      IsNavigating = false; 

      //blabla...... 
     } 

     System.Diagnostics.Debug.WriteLine("goto: [origin] {0} [dest] {1}", uri, endUri); 

     return endUri; 
    } 
} 

in App.cs:

RootFrame.Navigating += (s, e) => 
     { 
      AppUriMapper.IsNavigating = true; 
      System.Diagnostics.Debug.WriteLine("goto: [mode] {0}, [uri] {1}", e.NavigationMode, e.Uri); 
     }; 

Blick ok.