Xamarin.Forms & MvvmCross: навигация и команды не работают - PullRequest
1 голос
/ 27 февраля 2020

Я создал 4 проекта:

  • MobileApp.Core, который содержит мой бизнес-код (. NET Стандартная библиотека 2.0)
  • MobileApp.Droid (для Android 9)
  • MobileApp.iOS (для iOS 11)
  • MobileApp.UI, который содержит проект Xamarin.Forms (XAML)

... с некоторыми пакетами NuGet: Xamarin.Forms 4.4.0.X, MvvmCross.Forms 6.4.2, Xamarin.Essentials 1.4.0, Xamarin.Android.Support.XXX 28.X.X, ...

  • HomePage и SecondPage наследуются от MvxContentPage<TViewModel> (в C# класс и в файле XAML).
  • HomeViewModel и SecondVieWModel наследуются от BaseViewModel, который наследуется от MvxViewModel.

У меня есть некоторые службы в моем BaseViewModel введено в конструктор: IMvxNavigationService, MyApp.Core.Services.IMyCustomService. Они работают: IMyCustomService зарегистрирован в методе MyApp.Core.App.Initialize().

В моем HomeViewModel есть свойство MyText (привязано к Entry: <Entry Text="{Binding MyText}"/>) и команда ( привязано к ToolbarItem: <ToolbarItem Text="Ok" Command="{Binding OkCommand}"/>):

private string _myText;
public string MyText
{
    get => _myText;
    set => SetProperty(ref _myText, value);
}

public IMvxCommand OkCommand => new MvxAsyncCommand(ExecuteOkCommandAsync, CanExecuteOkCommand);
private async Task ExecuteOkCommandAsync()
{
    await MyCustomService.SomeAsyncWork(); // it works
    await NavigationService.Navigate<MissionsViewModel>();
}
private bool CanExecuteOkCommand() => !string.IsNullOrWhiteSpace(MyText);

2 неожиданных поведения

Команда остается недоступной

Когда я что-то печатаю в своей записи, привязывается к MyText свойство, команда остается недоступной. Я не знаю почему. _myText действительно установлено.

Я пытался использовать SetProperty(ref T storage, T value, Action afterAction, string propertyName) и вызывать OkCommand.RaiseCanExecuteChanged(), когда я уведомляю, что мое свойство было изменено:

public string MyText
{
    get => _myText;
    set => SetProperty(ref _myText, value, () => OkCommand.RaiseCanExecuteChanged(), nameof(MyText));
}

Моя команда остается недоступной. На данный момент, это готовность, я заменил CanExecuteOkCommand на () => true.

Не могу перейти от HomeViewModel.Initialize() метода (✔ решено)

Теперь я хотите перейти от HomeViewModel к SecondViewModel, если что-то верно (файл существует). Мне не нужны параметры.

В методе ExecuteOkCommandAsync я вызываю await NavigationService.Navigate(typeof(SecondViewModel));. Когда я перемещаюсь отсюда (команда вызывается), все в порядке.

Но когда я пытаюсь перейти из метода HomeViewModel.Initialize(), я вижу HomeViewModel со знаком * * кнопка на панели инструментов:

public override async Task Initialize()
{
    IsBusy = true;

    if (true) // a real condition : if file exists, today is monday, ...
    {
        var result = await NavigationService.Navigate<SecondViewModel>();
    }

    var items = await MyCustomService.GetItemsAsync();
    Items = new ObservableCollection<Item>(items);

    IsBusy = false;
}

При пошаговой отладке: вызывается

  1. HomeViewModel.Initialize(). var result = await NavigationService.Navigate<SecondViewModel>(); тоже.
  2. SecondViewModel.Initialize() вызывается.
  3. предыдущая переменная resultHomeViewModel.Initialize()) равна true.
  4. Приложение показывает HomePage (не SecondPage, как ожидалось).

enter image description here

Когда я нажимаю кнопку «ОК», на панели инструментов я могу перейти к реальному SecondPage (и его SecondViewModel, очевидно).

Когда я нажимаю кнопку возврата, с HomePage я перехожу на SecondPage ...

1 Ответ

0 голосов
/ 27 февраля 2020

Я могу переопределить метод ViewAppeared вместо Initialize задача:

public class HomeViewModel 
{
    /* Ommited code  */
    public override async Task Initialize()
    {
        IsBusy = true;
        var items = await MyCustomService.GetItemsAsync();
        // ...
    }

    public override void ViewAppeared()
    {
        base.ViewAppeared();
        if (true)
        {
            NavigationService.Navigate<MissionsViewModel>();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...