假设我在视图中有一些列表控件,我从中选择一个名称,这会在viewmodel中设置一个'SelectedName'属性。选择名称后,我想异步获取与该名称关联的一组数据,并使用该数据设置另一个属性,然后更新绑定到该其他数据属性的视图中的另一个控件。
不能对属性使用async / await,因此无法在'SelectedName'设置器中进行请求和赋值。
此案例的MVVM最佳做法是什么?
我在想,也许选择名称也可以触发viewmodel中的命令(RelayAsyncCommand)的执行,该命令可以执行异步获取和分配工作。但有没有保证在命令执行之前更新命令所需的'SelectedName'?
答案 0 :(得分:4)
与任何异步UI一样,您需要考虑的第一件事是其他状态会是什么样子。具体来说,你现在有一个" Loading"状态,现在也是思考你的错误"的好时机。状态。
我开发了my MSDN article on async data binding中描述的类型,它的行为类似于数据绑定Task<T>
。使用该类型,您可以执行以下操作:
public string SelectedName
{
get { return _selectedName; }
set
{
_selectedName = value;
OnPropertyChanged();
SelectedNameDetails = new NotifyTaskCompletion<SelectedNameData>(FetchNameDataAsync());
}
}
public NotifyTaskCompletion<SelectedNameData> SelectedNameDetails
{
get { return _selectedNameDetails; }
set { _selectedNameDetails = value; OnPropertyChanged(); }
}
然后,您可以数据绑定到SelectedNameDetails.Result
以在加载时显示详细信息;和SelectedNameDetails.IsNotCompleted
,SelectedNameDetails.IsSuccessfullyCompleted
和SelectedNameDetails.IsFaulted
可在“加载”,“成功”和“错误”视图状态之间切换。
答案 1 :(得分:0)
虽然您无法直接在SelectedName
setter中执行异步操作,但您仍然可以在setter中调用async void
方法来执行所有异步逻辑并设置第二个属性。唯一的缺点是这个方法在完成后无法通知SelectedName
setter(因为它必须是void
),但在你的情况下这不应该是必要的吗?