我有一个具有以下属性的ViewModel
public Employee SelectedEmployee
{
get { return _selectedEmployee; }
set
{
if (value == _selectedEmployee) return;
_selectedEmployee = value;
if (_selectedEmployee != null)
{
StaffHolidaysViewModel.HolidayAllowance = _staffDataService.EmployeeHolidayAllowance(_selectedEmployee.Id);
FireEmployeeSelectedMessage(SelectedEmployee.Id);
}
RaisePropertyChanged();
RaisePropertyChanged(nameof(Allowance));
RaisePropertyChanged(nameof(Taken));
RaisePropertyChanged(nameof(Remaining));
RaisePropertyChanged(nameof(TotalAbsences));
RaisePropertyChanged(nameof(TotalSick));
RaisePropertyChanged(nameof(TotalNonSickAbsences));
RaisePropertyChanged(nameof(SelectedEmployeeLeavingDate));
UpdateCanExecuteChanged();
}
}
该行
StaffHolidaysViewModel.HolidayAllowance = _staffDataService.EmployeeHolidayAllowance(_selectedEmployee.Id);
包含对我想要异步的方法的调用。我不知道如何做到这一点,因为SelectedEmployee是一个绑定属性。
<ComboBox Name="StaffMembers" ItemsSource="{Binding FilteredEmployees}" SelectedItem="{Binding SelectedEmployee}" Width="200" BorderThickness="1" BorderBrush="DimGray">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
由于它是属性,我无法进行类型Task<Employee>
异步绑定MVVM属性的推荐方法是什么?或者这是不可能的?
答案 0 :(得分:3)
为什么?让我们从另一个角度来看待它:
异步意味着UI线程不会停止(UI在处理时不会挂起),而主处理线程会等待操作完成并获得结果(考虑到你是否正在使用await
)。
当您定义绑定时,UI直接依赖于使用等待的数据的属性,这意味着UI必须等待(这不会发生在async
操作中),因此属性可以&#39;不能async
,因此您无法使用await
。
我现在使用的所有解决方法:
.Result
的异步任务返回方法的属性。我试过了,它并没有提供最好的输出。IAsyncOperation<>
而不是Task<>
。这将为您提供调用.GetResults()
方法的优势,该方法将为您提供结果,并且不会冻结您的UI线程。有关它的更多信息here。如果您没有要执行的任何结果提取操作,请使用此选项。 Task<>
的异步方法。我在那里执行所有操作并验证结果。获得我需要的结果后,我只需更新属性并调用RaisePropertyChanged
即可。这种方式我也可以处理其他视图处理或中间加载屏幕,而不必受限于不能停止处理线程。 使用我在顶部定义的三种方法中的任何一种。他们一切都很好。以下是用例来获取游戏的得分表单服务器的用例摘要:
IAsyncOperation<>
。代码处理不会停止或等待进程获得结果。例如:你只需获取分数并显示它。Task<>
返回方法。例如:您希望在计算得分后将整数值转换为百分比。.Result
但它对我来说并不适用。 如果还有其他任何内容可以在评论中随意提及
答案 1 :(得分:3)
包含对我想要异步的方法的调用。
我有一篇关于async MVVM data binding的文章。基本上,我通常做的是创建一个可绑定数据的Task
- 我在文章中称之为NotifyTaskCompletion
,缩写为NotifyTask
in my updated library。
您可以通过将StaffHolidaysViewModel.HolidayAllowance
的类型从它(我将其称之为THolidayAllowance
)更改为NotifyTask<T>
包装器(例如NotifyTask<THolidayAllowance>
来使用它})。
然后,您可以同步设置它:
StaffHolidaysViewModel.HolidayAllowance = NotifyTask.Create(
_staffDataService.EmployeeHolidayAllowanceAsync(_selectedEmployee.Id));
您在此处所做的是开始 EmployeeHolidayAllowanceAsync
,然后使用Task
将其NotifyTask
包裹起来。这是同步完成的,因此可以在属性设置器中执行此操作。
然后,您的数据绑定也需要更新。 NotifyTask<T>
has several properties that you can use。最明显的是Result
,它最终会保存EmployeeHolidayAllowanceAsync
的结果(它会返回默认值,直到EmployeeHolidayAllowanceAsync
完成)。还有IsNotCompleted
和IsFaulted
,您希望用它来向用户表明数据尚未到达或存在某些错误。< / p>