【问题标题】:Xamarin.Forms & MvvmCross : Navigation and commands not workXamarin.Forms & MvvmCross:导航和命令不起作用
【发布时间】:2020-02-26 23:54:09
【问题描述】:

我创建了 4 个项目:

  • MobileApp.Core,其中包含我的业务代码(.NET Standard 2.0 库)
  • MobileApp.Droid(适用于 Android 9)
  • MobileApp.iOS(适用于 iOS 11)
  • MobileApp.UI,其中包含 Xamarin.Forms 项目 (XAML)

...带有一些 NuGet 包:Xamarin.Forms 4.4.0.XMvvmCross.Forms 6.4.2Xamarin.Essentials 1.4.0Xamarin.Android.Support.XXX 28.X.X、...

  • HomePageSecondPage 继承自 MvxContentPage<TViewModel>(在 C# 类和 XAML 文件中)。
  • HomeViewModelSecondVieWModel 继承自 BaseViewModel,后者继承自 MvxViewModel

我的BaseViewModel 中有一些服务注入到构造函数中:IMvxNavigationServiceMyApp.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 替换为 () =&gt; true

无法从HomeViewModel.Initialize() 方法导航(✔ 已解决)

现在,如果某些情况属实(文件存在),我想从 HomeViewModel 导航到 SecondViewModel。我不需要参数。

ExecuteOkCommandAsync 方法中,我调用await NavigationService.Navigate(typeof(SecondViewModel));。当我从这里导航时(调用命令),没关系。

但是当我尝试从 HomeViewModel.Initialize() 方法导航时,我看到了 HomeViewModel 的视图,工具栏中有一个 *back* 按钮:

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&lt;SecondViewModel&gt;(); 也是。
  2. SecondViewModel.Initialize() 被调用。
  3. 之前的result 变量(在HomeViewModel.Initialize() 中)是true
  4. 应用程序显示HomePage(而不是预期的SecondPage)。

当我点击工具栏中的“确定”按钮时,我可以导航到真正的SecondPage(显然还有他的SecondViewModel)。

当我按下返回按钮时,从 HomePage 导航到 SecondPage...

【问题讨论】:

  • 如果在任何可能的交互之前条件为真,我发现从HomePage 导航到SecondPage 的唯一方法是覆盖ViewAppeared 方法。

标签: c# xamarin xamarin.forms


【解决方案1】:

我可以覆盖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>();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-08
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多