MvvmCross视图模型初始化完成

3
在MvvmCross的第五个版本中,添加了一个异步的Initialize重载方法,你可以在其中进行大量数据的异步加载。
public override async Task Initialize()
{
    MyObject = await GetObject();
}

有没有一种方法可以在View中确定初始化已经完成了?例如,在View中,我想将工具栏标题设置为显示MyObject中的某个字段。
    MyViewModel vm;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        // Create your application here

        this.SetContentView(Resource.Layout.MyView);

        var toolbar = (Toolbar)FindViewById(Resource.Id.toolbar);
        SetSupportActionBar(toolbar);

        vm = (MyViewModel)this.ViewModel;

        SupportActionBar.Title = vm.MyObject.Name;

    }

在设置 SupportActionBar.Title 的那一行中,有没有确定初始化任务是否完成的方法?如果未完成,是否可以在完成后得到通知?
更新: 我尝试设置了两个正确的答案,因为 @nmilcoff 回答了我的实际问题,而 @Trevor Balcom 向我展示了更好的方法。
3个回答

6

是的,您可以订阅InitializeTask的属性更改。

类似以下内容即可:

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    // your code

    ViewModel.PropertyChanged += MyViewModel_PropertyChanged;
}

private void MyViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if(e.PropertyName == nameof(ViewModel.InitializeTask) && ViewModel.InitializeTask != null)
    {
        ViewModel.InitializeTask.PropertyChanged += ViewModel_InitializeTask_PropertyChanged;
    }
}

private void ViewModel_InitializeTask_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if(e.PropertyName == nameof(ViewModel.InitializeTask.IsSuccessfullyCompleted))
        SupportActionBar.Title = ViewModel.MyObject.Name;
}

当然,仅仅监听 ViewModel.MyObject.Name 属性的更改可能更容易。但上述是一种通用的方法来监听 InitializeTask 属性的变化。
您可以在官方文档中了解更多关于 InitializeTask 和 MvxNotifyTask 的信息。

我之前尝试过这种方法,但问题在于Initialize()在你挂接PropertyChanged事件之前被调用,如果它在你挂接事件之前完成,你的事件处理程序就永远不会得到通知。我看过MvxNotifyTask,但它没有说明如何将其连接到监听Initialize()任务。我将查看InitializeTask,看看是否可能是答案。 - Jim Wilcox
我没有看到ViewModel上有一个名为InitializeTask的属性。 - Jim Wilcox
没关系。我必须更新到最新版本的MvvmCross。 - Jim Wilcox
做到了。谢谢兄弟。 - Jim Wilcox

2
在Xamarin Forms中: 我想要在VM中添加属性更改事件的登录以便进行测试,因此: View.xaml.cs
protected override void OnViewModelSet()
{
    base.OnViewModelSet();
    var vm = this.DataContext as SearchMovieViewModel;
    if (vm is null)
    {
        return;
    }

    vm.OnViewModelSet();
}

在您的ViewModel中:

/// <summary>
/// This method should be called in every View Code Behind when you
/// need to subscribe to InitializeTask changes.
/// </summary>
public void OnViewModelSet()
{
    if (this.InitializeTask is null)
    {
        return;
    }
    this.InitializeTask.PropertyChanged += this.InitializeTask_PropertyChanged;
}

最后,在您的视图模型中实现任何必要的MvvmCross InitializeTask检查,对于我来说,我使用了IsCompleted属性,但您可以使用任何您需要的属性:

private void InitializeTask_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(this.InitializeTask.IsCompleted))
    {
        // do something
    }
}

不要忘记取消订阅,例如当视图被销毁时。您可以在您的视图模型中重写此方法:

public override void ViewDestroy(bool viewFinishing = true)
{
        base.ViewDestroy(viewFinishing);
        this.InitializeTask.PropertyChanged -= this.InitializeTask_PropertyChanged;
}

1
工具栏还支持像这样绑定Title属性的数据绑定:
<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:popupTheme="@style/AppTheme.PopupOverlay"
    app:MvxBind="Title MyObject.Name" />

这是我想要做的更好的方法。它不会让我设置多个正确答案,所以我不得不选择回答实际问题的那个。我正在检查我的代码,并使用你的方法来设置所有内容的标题。谢谢兄弟。 - Jim Wilcox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接