操纵后台时WinRT应用程序中的COMException

时间:2016-06-09 13:46:16

标签: windows-runtime windows-phone-8.1 mvvmcross comexception

最终更新

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

我正在编写Windows Phone 8.1应用程序。因为我正在使用MVVMcross,所以我有一个经典的项目设置:一个包含ViewModels的便携式项目和一个包含Views的Windows Phone 8.1项目。

在某些情况下,我想从Backstack中删除一个页面,以便在单击后退按钮时显示删除页面之前的页面。

为了实现这种行为,我单独关注这个例子: https://edsnider.net/2014/04/07/clearing-windows-phone-nav-back-stack-in-mvvmcross/

除非我在应用程序中完成重新启动并再次重新打开应用程序,否则一切正常。在这种情况下,当我进行Backstack操作时,我得到一个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
    });

这是我的ViewModel的基类。 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());
    }
}

正在进行Backstack操作的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);
    }
}

我在网上只发现了一个对此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: \n\n" + 
        e.Message + "\n\n" +
        e.Exception.HResult + "\n\n" +
        e.Exception.Message + "\n\n" +
        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

仅在应用程序在发布模式下构建时才会引发异常。在调试模式下不会发生。我必须重新启动设备才能实现它。

1 个答案:

答案 0 :(得分:0)

我认为问题就是你这样说的方式。 首先,您调用ShowViewModel,然后您想从堆栈中删除页面。 听起来就像在发布模式下它会被同时调用,所以你得到这个消息。

0

在你的主持人那里:

public class DropCurrentBackStackEntryHint : MvxPresentationHint
{
    public Type ViewModelType;

    public DropCurrentBackStackEntryHint(Type viewModelType)
    {
        ViewModelType = viewModelType;
    }
}

另一种解决方案,不是很好的方式: 当您始终要从堆栈中删除最后一页时,当您导航到此页面时,您可以从视图后面的代码中的Backstack中删除最后一页。

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);
        }
    }

    ...
}