Caliburn.Micro Go Back, вызываемый при активации, не работает в WinRT

Этот вопрос относится к Windows Phone 8.1 (WinRT); это также может быть применимо к Windows 8.1. Я использую Caliburn.Micro 2.0.1

В моем ViewModel OnActivate я проверяю, является ли элемент базой данных, и если это не так, я хочу вернуться на предыдущую страницу.

Упрощенным решением будет просто вызвать GoBack в методе OnActivate (это работает в Windows Phone 8.0):

INavigationService _navigationService;
protected override void OnActivate()
{
    _item = GetItemFromDB();
    if(_item == null)
    {
       _navigationService.GoBack() 
    }
}

Чтобы перейти к модели представления, я вызываю:

_navigationService.NavigateToViewModel<MyViewModel>(_param);

Но это не работает, игнорирует вызов GoBack и остается на странице, которую я не хочу просматривать.

Просматривая код, вы можете видеть, что код GoBack вызывается внутри метода NavigateToViewModel; Я ожидаю, что это причина, по которой он не работает (может быть, что-то связанное с проблемой очереди?).

У меня есть очень "хакерское" решение, которое включает таймер (который работает), но я действительно презираю его, поскольку оно склонно к проблемам с потоками и может быть вызвано во время вызова NavigateToViewModel (если оно занимает много времени), что снова не сработает:

protected override void OnActivate()
{
    _item = GetItemFromDB();
    if(_item == null)
    {
        DispatcherTimer navigateBackTimer = new DispatcherTimer();
        navigateBackTimer.Interval = TimeSpan.FromMilliseconds(300);
        navigateBackTimer.Tick += GoBackAfterNavigation;
        navigateBackTimer.Start();
    }
}

public void GoBackAfterNavigation(object sender, object e)
{
    _navigationService.GoBack();
    (sender as DispatcherTimer).Stop();
}

Есть ли лучший способ вернуться назад? Почему GoBack не работает в OnActivate? Есть ли способ заставить его работать в OnActivate?


person Barnstokkr    schedule 19.12.2014    source источник


Ответы (1)


Ты можешь использовать

Execute.OnUIThreadAsync(() => /* navigationCode */);

вместо таймера поставить действие в очередь сразу после завершения обработки текущего стека.

person Frank    schedule 19.12.2014
comment
Оно работает! Спасибо! Почему это работает, объясните пожалуйста. Это асинхронность или поток пользовательского интерфейса? - person Barnstokkr; 19.12.2014
comment
Очевидно, что в WP8.1 есть проблема, когда вы в данный момент осуществляете навигацию и пытаетесь перейти туда. Похоже, это ошибка в caliburn.micro. Код использует Dispatcher, чтобы поместить ваш навигационный вызов за текущим исполняемым кодом. - person Frank; 19.12.2014