c# - WP8 : Fast app resume + secondary tile + MainPage = 2 instances

标签 c# windows-phone-8 windows-phone secondary-live-tile

我在这里遇到了同样的问题:

http://social.msdn.microsoft.com/Forums/wpapps/en-us/af8615e7-8e90-4069-aa4d-3c4a84a6a3d0/windows-phone-8-fast-app-resume-with-deeplinks?forum=wpdevelop

我不是 C# 或 WP 专家,所以请多多包涵。

  • 我有链接到“/MainPage.xaml?id=XX”的辅助磁贴。
  • 我启用了快速应用恢复。 (应用 list 中的 ActivationPolicy="Resume")
  • 我的应用程序中只有一个页面:MainPage.xaml。

问题:当我使用辅助磁贴(“/MainPage.xaml?id=XX”)恢复应用程序时,我得到了前一个实例(本来可以恢复)的简要 View ,并且然后 MainPage 再次初始化,创建一个新实例。实际上,在让我看到之前打开的内容后,该应用程序正在从头开始加载。

这显然是不受欢迎的行为。我想使用现有实例来执行我​​的任务。


尝试 1: 使用 e.Cancel = true; 取消到 MainPage.xaml 的导航:
(使用来自官方 Fast App Resume sample 的 App.xaml.cs 代码来识别应用程序是如何启动的)

...
else if (e.NavigationMode == NavigationMode.New && wasRelaunched)
{
  // This block will run if the previous navigation was a relaunch
  wasRelaunched = false;

  if (e.Uri.ToString().Contains("="))
  {
    // This block will run if the launch Uri contains "=" (ex: "id=XX") which
    // was specified when the secondary tile was created in MainPage.xaml.cs
    sessionType = SessionType.DeepLink;

    e.Cancel = true; // <======================== Here

    // The app was relaunched via a Deep Link.
    // The page stack will be cleared.
  }
}
...

问题:这样做时,我的 OnNavigatedTo 事件处理程序永远不会触发,所以我的查询字符串永远不会被解析。

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
  String navId;
  if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
  {
    if (NavigationContext.QueryString.TryGetValue("id", out navId))
    {
      MessageBox.Show(navId.ToString()); // Not reached
    }
  }
  ...

尝试 2: 使用 e.Cancel = true; 取消到 MainPage.xaml 的导航,AND 将 Uri 传递给 MainPage 中的方法:

// App.xaml.cs
...
else if (e.NavigationMode == NavigationMode.New && wasRelaunched)
{
  // This block will run if the previous navigation was a relaunch
  wasRelaunched = false;

  if (e.Uri.ToString().Contains("="))
  {
    // This block will run if the launch Uri contains "=" (ex: "id=XX") which
    // was specified when the secondary tile was created in MainPage.xaml.cs
    sessionType = SessionType.DeepLink;

    e.Cancel = true;

    MainPage.GoToDeepLink(e.Uri); // <======================== Here

    // The app was relaunched via a Deep Link.
    // The page stack will be cleared.
  }
}
...

// MainPage.xaml.cs
public static void GoToDeepLink(Uri uri) // <======================== Here
{
  // Convert the uri into a list and navigate to it.
  string path = uri.ToString();
  string id = path.Substring(path.LastIndexOf('=') + 1);

  MyList list = App.ViewModel.ListFromId(Convert.ToInt32(id));
  pivotLists.SelectedItem = list;
}

问题:我得到一个错误,指出 pivotLists 是非静态的,因此需要一个对象引用。我认为,为了让它工作,我需要创建一个 MainPage 的新实例 (MainPage newMainPage = new MainPage();) 并调用 newMainPage.pivotLists.SelectedItem = list ; -- 但我不知道如何使用 newMainPage 而不是现有的/替换它...或者如果那是我想要的东西/不会导致进一步的问题/并发症。


我不知道这个问题的解决方案是什么,我可能会朝着完全错误的方向前进。如果可以的话,请用简单的代码示例保留所有建议,我还在学习。

感谢您的帮助。

最佳答案

似乎当您从辅助磁贴重新打开您的应用程序时,它会重新激活并创建 MainPage 的新实例(即使有一个来自上一次运行)。如果我对你的理解是正确的,我已经设法做到了这样的事情:

在 app.xaml.cs 中:

我添加了一个变量,指示从辅助磁贴导航后是否应该返回到之前的 MainPage - 它需要是静态的,因为我想从 MainPage 访问它

public static bool returnPage = false;

在 RootFrame_Navigating 中,我将此变量设置为 true:

// ...
else if (e.NavigationMode == NavigationMode.New && wasRelaunched)
{
   // This block will run if the previous navigation was a relaunch
   wasRelaunched = false;
   returnPage = true;
// ...

在 ClearBackStackAfterReset 中 - 防止在返回时删除旧页面:

// ...
if (e.NavigationMode != NavigationMode.New || returnPage)
      return;
// ...

在 MainPage.cs 中:

我更改了一些构造函数,因为我不想看到新页面的闪烁:

public MainPage()
{
  if (!App.returnPage)
     InitializeComponent();
}

在 MainPage 中,我还有从辅助磁贴传递的变量 - 它也是静态的,因为我只需要它的一个实例:

private static string navId = "";

技巧的核心 - OnNavigatedTo:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  if (App.returnPage)
  {
     App.returnPage = false;
     NavigationContext.QueryString.TryGetValue("id", out navId);
     NavigationService.GoBack();
  }
  else if (e.NavigationMode != NavigationMode.Reset)
  {
     // normal navigation
  }
}

它是这样工作的:

  • 当您正常启动您的应用程序时,returnPage 为 false,一切正常
  • 当您从辅助磁贴激活它时,会发生一些事情:

    1.首先使用 NavigationMode.Reset 导航到您的上一页 - 我们对此不感兴趣,所以我将其关闭 - 什么都不会发生
    2. 然后程序尝试创建 MainPage 的新实例,但 returnPage 为真,并且由于 if 语句,InitializeComponent 不会运行。在此之后,在 OnNavigatedTo 中,程序保存传递的查询字符串并导航回到 MainPage 的前一个实例 - 来自上一次运行
    3. 最后,我们使用 NavigationMode.Back 导航到右侧 MainPage,我们将查询字符串保存在静态变量中。

您必须注意两件事:首先 - 可能它可以进行少量重建(我不确定是否需要 wasRelaunched 等等) - 您需要对其进行调试并查看可以删除的内容。其次 - 您可能需要使用 Tombstone 案例测试您的应用。

希望这对您有所帮助。

关于c# - WP8 : Fast app resume + secondary tile + MainPage = 2 instances,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21585393/

相关文章:

windows-phone - 如何在开发帐户中注册我的 WP 设备?

html - Windows Phone Internet Explorer 在一个 td 中放大文本

c# - 无法通过 HTTP 响应从文件下载创建 DotNetZip ZipFile

c# - 将复选框添加到 UniformGrid

MVVM Light - 将项目选择传达给 ViewModelSelector

windows-phone-8 - 替代 tlsAlloc tlsGetValue 和 tlsSetValue

c# - 如何将 Picture Box 单击事件组合成一个?

c# - 我如何使用 C# 从 tabcontrol 中删除选项卡

c# - Windows Phone 8 - Mac 地址

c# - 打开/关闭 Windows Phone 设置