Я создал 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;
}
При пошаговой отладке: вызывается
HomeViewModel.Initialize()
. var result = await NavigationService.Navigate<SecondViewModel>();
тоже. SecondViewModel.Initialize()
вызывается. - предыдущая переменная
result
(в HomeViewModel.Initialize()
) равна true
. - Приложение показывает
HomePage
(не SecondPage
, как ожидалось).
Когда я нажимаю кнопку «ОК», на панели инструментов я могу перейти к реальному SecondPage
(и его SecondViewModel
, очевидно).
Когда я нажимаю кнопку возврата, с HomePage
я перехожу на SecondPage
...