操作后台文件时WinRT应用程序中出现COMException



最终更新

我发现了问题。这与背后操纵无关。原因是我没有正确注册资源字典


我正在写一个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);
}
...
}

最新更新