我正在尝试做一些可能是坏主意的事情,但我认为这仍然是可能的。我试图覆盖WP8如何处理后退按钮并自己实现它。我认为如果我:
PhoneApplicationPage.BackKeyPress
。Here's a sample project that has the crash
..然后它应该工作。但是,我的尝试被Windows Phone挫败了。 Here's the code:
// This basically happens on PhoneApplicationService.OnLaunched
_viewModelChanged.StartWith(ViewModel).Where(x => x != null).Subscribe(vm => {
var page = default(IViewFor);
var frame = RootVisual as PhoneApplicationFrame;
// Find the initial PhoneApplicationPage for the app
page = RxApp.GetService<IViewFor>("InitialPage");
// Depending on how we're being signalled (i.e. if this is cold start
// vs. resume), we need to create the PhoneApplicationFrame ourselves
if (frame == null) {
frame = new PhoneApplicationFrame() {
Content = page,
};
}
page.ViewModel = vm;
var pg = page as PhoneApplicationPage;
if (pg != null) {
pg.BackKeyPress += (o, e) => {
if (ViewModel.Router.NavigationStack.Count <= 1 ||
ViewModel.Router.NavigateBack.CanExecute(null)) {
return;
}
e.Cancel = true;
ViewModel.Router.NavigateBack.Execute(null);
};
}
// Finally, set Application.RootVisual
RootVisual = frame;
});
这很有效,直到在执行此代码之后,框架排队的DispatcherItem会崩溃应用程序:
System.NullReferenceException occurred
Message: A first chance exception of type 'System.NullReferenceException' occurred in Microsoft.Phone.ni.dll
Microsoft.Phone.ni.dll!Microsoft.Phone.Controls.PhoneApplicationPage.InternalOnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) Unknown
Microsoft.Phone.ni.dll!Microsoft.Phone.Controls.PhoneApplicationPage.Microsoft.Phone.Controls.IPhoneApplicationPage.InternalOnNavigatedFromX(System.Windows.Navigation.NavigationEventArgs e) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.RaiseNavigated(object content, System.Uri uri, System.Windows.Navigation.NavigationMode mode, bool isNavigationInitiator, Microsoft.Phone.Controls.IPhoneApplicationPage existingContentPage, Microsoft.Phone.Controls.IPhoneApplicationPage newContentPage) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.CompleteNavigation(System.Windows.DependencyObject content, System.Windows.Navigation.NavigationMode mode) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.NavigationService.ContentLoader_BeginLoad_Callback(System.IAsyncResult result) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(System.AsyncCallback userCallback, System.Windows.Navigation.PageResourceContentLoader.PageResourceContentLoaderAsyncResult result) Unknown
Microsoft.Phone.ni.dll!System.Windows.Navigation.PageResourceContentLoader.BeginLoad.AnonymousMethod__0(object args) Unknown
[Native to Managed Transition]
mscorlib.ni.dll!System.Delegate.DynamicInvokeImpl(object[] args) Unknown
System.Windows.ni.dll!System.Windows.Threading.DispatcherOperation.Invoke() Unknown
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority) Unknown
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context) Unknown
System.Windows.ni.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args) Unknown
System.Windows.RuntimeHost.ni.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam* pParams, System.Windows.Hosting.NativeMethods.ScriptParam* pResult) Unknown
答案 0 :(得分:5)
所以,我已经解决了这个问题 - 我的代码存在问题,因为我没有弄清楚WP8是如何工作的:)这就是我现在所理解的,这可能也是错的,但我还是会写的
PhoneApplicationFrame
PhoneApplicationFrame
似乎还设置了一个全局静态变量(在App.xaml中创建PhoneApplicationService
时也会发生相同的事情,它会设置PhoneApplicationService.Current
) 。 NavigationService
然后尝试通过资源字符串(即'/MainPage.xaml'
)重新创建XAML视图。它会重新创建以前被逻辑删除的那个,或者如果没有,它默认为WMAppManifest中的那个(这是我不理解的部分)。PhoneApplicationFrame.Navigated
被NavigationService调用 - 这是你可以实际开始做的事情,包括最重要的是,设置Application.RootVisual ,这将发送Loading ...屏幕< / LI>
PhoneApplicationService.Launched
或PhoneApplicationService.Activated
一旦基本上全部设置完毕,最终会触发,具体取决于您的应用被唤醒的方式。答案 1 :(得分:4)
发现了这个问题。好吧,冰山一角。
InternalOnNavigatedFrom方法的代码是:
internal override void InternalOnNavigatedFrom(NavigationEventArgs e)
{
PhoneApplicationPage content = e.Content as PhoneApplicationPage;
string str = ((content == null) || (content.Title == null)) ? string.Empty : content.Title;
PerfUtil.BeginLogMarker(MarkerEvents.TH_ONNAVIGATEDFROM_PAGE, string.Format("{0},{1},{2}", (base.Title == null) ? "" : base.Title, e.NavigationMode, str));
this.OnNavigatedFrom(e);
PerfUtil.EndLogMarker(MarkerEvents.TH_ONNAVIGATEDFROM_PAGE, string.Format("{0},{1},{2}", (base.Title == null) ? "" : base.Title, e.NavigationMode, str));
DeviceStatus.KeyboardDeployedChanged -= new EventHandler(this.OnKeyboardDeployedChanged);
Task rootTask = ApplicationHost.Current.RootTask;
rootTask.OnVisibleRegionChange = (ITask.VisibleRegionChanged) Delegate.Remove(rootTask.OnVisibleRegionChange, new ITask.VisibleRegionChanged(this.OnVisibleRegionChange));
Task task2 = ApplicationHost.Current.RootTask;
task2.OnSipVisibilityChange = (ITask.SipVisibilityChange) Delegate.Remove(task2.OnSipVisibilityChange, new ITask.SipVisibilityChange(this.OnSipVisibilityChange));
this._lastSipHeight = 0.0;
this._dictionary = null;
}
经过一些调试后,我得出结论:e
或Application.Current.RootTask
都不为空。在我挠头之后,我查看了KeyboardDeployedChanged
事件处理程序的代码:
public static event EventHandler KeyboardDeployedChanged
{
[SecuritySafeCritical] add
{
if (KeyboardDeployedSubscription == null)
{
KeyboardDeployedSubscription = new SubscriptionHandler(DeviceTypes.KeyBoard);
}
KeyboardDeployedSubscription.Changed += value;
}
[SecuritySafeCritical] remove
{
KeyboardDeployedSubscription.Changed -= value;
}
}
这段代码编写得很糟糕。如果在remove
之前调用处理程序的add
部分,KeyboardDeployedSubscription
将为null并且将引发异常。为了测试我的理论,我订阅了App
的构造函数中的事件:
public App()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
DeviceStatus.KeyboardDeployedChanged += (sender, e) => { };
果然,异常消失了。现在,为了理解你的代码为什么触发这个问题,我回溯到框架的哪个部分应该订阅该事件。唯一的候选者是InternalOnNavigatedTo
方法。
因此,您的问题是,即使OnNavigatedFrom
从未被调用,也会调用OnNavigatedTo
。
答案 2 :(得分:1)
由于您正在使用Windows Phone的内置自动导航到WMAppManifest.xml中定义的页面,我尝试删除自动导航,它基本上有效(没有例外)。
我刚刚更换了
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
带
<DefaultTask Name="_default" />
不确定这是否能解决您的问题,但至少不会再崩溃。