最终更新
我发现了问题。这与背后操纵无关。原因是我没有正确注册资源字典
我正在写一个Windows Phone 8.1应用程序。因为我使用MVVMcross,所以我有一个经典的项目设置:一个包含ViewModels的可移植项目和一个包含View的Windows Phone 8.1项目。
在某些情况下,我想从后台删除一个页面,这样当我单击后退按钮时,将显示删除页面之前的页面。
为了实现这种行为,我独自遵循了这个例子:https://edsnider.net/2014/04/07/clearing-windows-phone-nav-back-stack-in-mvvmcross/
除了当我在应用程序中完全重新启动并再次打开应用程序时,一切都很好。在这种情况下,当我进行后台操作时,我会遇到COM异常:
The operation identifier is not valid.
The BackStack or ForwardStack cannot be changed while navigating.
问题:我的代码出了什么问题?
以下是相关的代码片段:
DropPageAndShowViewModel方法是在我的ViewModels的基类中定义的。当我在ViewModel:中调用此方法时发生异常
DropPageAndShowViewModel<TourdatenSummaryViewModel>(
new TourdatenSummaryViewModel.NavObject
{
Tournummer = _tour.Nummer
});
这是我的ViewModels的基类。BaseViewModel源自MvxViewModel。
public class BasePageViewModel : BaseViewModel
{
...
protected void DropPageAndShowViewModel<TViewModel>()
where TViewModel : BasePageViewModel
{
ShowViewModel<TViewModel>();
ChangePresentation(new DropCurrentBackStackEntryHint());
}
protected void DropPageAndShowViewModel<TViewModel>(object parameterValuesObject)
where TViewModel : BasePageViewModel
{
ShowViewModel<TViewModel>(parameterValuesObject);
ChangePresentation(new DropCurrentBackStackEntryHint());
}
}
是CustomViewPresenter进行后台操作:
public class DropCurrentBackStackEntryHint : MvxPresentationHint
{
}
public class CustomViewPresenter : MvxWindowsViewPresenter
{
private readonly IMvxWindowsFrame _rootFrame;
public CustomViewPresenter(IMvxWindowsFrame rootFrame) : base(rootFrame)
{
_rootFrame = rootFrame;
}
protected Frame RootFrame
{
get { return (Frame) _rootFrame.UnderlyingControl; }
}
public override void ChangePresentation(MvxPresentationHint hint)
{
if (hint is DropCurrentBackStackEntryHint)
{
if (RootFrame.BackStack.Any())
{
RootFrame.BackStack.RemoveAt(RootFrame.BackStackDepth - 1);
}
}
base.ChangePresentation(hint);
}
}
我在web中只找到一个对此COM异常的引用,但对我没有帮助:https://github.com/Windows-XAML/Template10/issues/454
更新
我在这个处理程序中捕获了未处理的异常:
void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (Debugger.IsAttached)
Debugger.Break();
e.Handled = true;
var message = "Error: nn" +
e.Message + "nn" +
e.Exception.HResult + "nn" +
e.Exception.Message + "nn" +
e.Exception.StackTrace;
new MessageDialog(message).ShowAsync();
}
当抛出异常时,我得到以下文本:
The operation identifier is not valid.
The BackStack or ForwardStack cannot be changed while navigating.
-2147020579
The operation identifier is not valid. (Exception from HRESULT: 0x800710DD)
HRESULT代码对我也没有帮助:
C:> err 0x800710DD
# as an HRESULT: Severity: FAILURE (1), Facility: 0x7, Code 0x10dd
# for hex 0x10dd / decimal 4317 :
ERROR_INVALID_OPERATION winerror.h
# The operation identifier is not valid.
# 1 matches found for "0x800710DD"
更新2
只有在应用程序以发布模式构建时才会引发异常。它不会在调试模式下发生。我必须重新启动设备才能生效。
我认为问题在于您调用它的方式。首先调用ShowViewModel,然后希望从堆栈中删除页面。听起来在发布模式下,它会同时被调用,所以你会收到这个消息。
public class DropCurrentBackStackEntryHint : MvxPresentationHint
{
public Type ViewModelType;
public DropCurrentBackStackEntryHint(Type viewModelType)
{
ViewModelType = viewModelType;
}
}
在您的演示者处:
public override void ChangePresentation(MvxPresentationHint hint)
{
...
if (hint is DropCurrentBackStackEntryHint)
{
var dropHint = (DropCurrentBackStackEntryHint) hint;
var nativeView = Mvx.Resolve<IMvxViewsContainer>().GetViewType(dropHint.ViewModelType);
RootFrame.Navigate(nativeView, null);
// Perhaps you need here a await Task.Delay(200); here. You have to test the value
if (RootFrame.BackStack.Any() && RootFrame.BackStack.Count > 1)
{
RootFrame.BackStack.RemoveAt(RootFrame.BackStackDepth - 2);
}
}
...
}
另一种不太好的解决方案:当您总是想从堆栈中删除最后一个页面时,当您导航到此页面时,您可以在视图的代码隐藏中从后台删除最后一页。
public partial class XyzView
{
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if(Frame.BackStack.Any() && Frame.BackStack.Count > 1)
Frame.BackStack.RemoveAt(Frame.BackStackDepth - 2);
}
...
}