C# MVVM和异步属性
我有一个具有以下属性的ViewModelC# MVVM和异步属性,c#,wpf,mvvm,async-await,C#,Wpf,Mvvm,Async Await,我有一个具有以下属性的ViewModel public Employee SelectedEmployee { get { return _selectedEmployee; } set { if (value == _selectedEmployee) return; _selectedEmployee = value;
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
对于异步绑定的MVVM属性,建议采用什么方法?或者说这是不可能的?从技术上讲,让属性执行异步任务并不是一种理想的方法,因为它们需要返回一个值 为什么?让我们从另一个角度来看: 异步意味着UI线程将不会停止(处理时UI不会挂起),而主处理线程将等待操作完成并获得结果(考虑到您正在使用的是
wait
)
定义绑定时,UI直接依赖于使用wait的数据的属性,这意味着UI必须等待(这在async
操作中无法发生),因此属性不能设置为async
,因此不能使用wait
我现在使用的所有解决办法是什么:
.Result
。我已经试过了,它并没有提供最好的输出IAsyncOperation
,而不是Task
。这将为您提供调用.GetResults()
方法的优势,该方法将获得结果,并且不会冻结UI线程。更多关于它的信息。如果没有要执行的任何后期结果获取操作,请使用此选项李>
Task
。我在那里执行所有操作并验证结果。一旦得到所需的结果,我只需更新属性并调用RaisePropertyChanged
。这样,我也可以处理其他视图处理或中间加载屏幕,而不必受到无法停止处理线程的限制李>
底线 使用我在上面定义的三种方法之一。他们都很好。下面是用例的总结点,以从游戏服务器获取分数为例:
IAsyncOperation
。代码处理不会停止或等待进程获得结果。你只要把分数拿出来并显示出来就行了Task
returning方法。计算分数后,您希望将整数值转换为百分比.Result
,但它从未对我起过作用李>
如果还有什么,请随时在评论中提及
包含对我要使其异步的方法的调用
我有一篇关于你的文章。本质上,我通常做的是创建一个可绑定的任务
——我在文章中称之为NotifyTaskCompletion
,简称为
您可以通过将StaffHolidaysViewModel.HolidayAllowance
的类型从任何类型(我将其称为THolidayAllowance
)更改为NotifyTask
包装器(例如,NotifyTask
)来使用它
然后,您可以同步设置它:
StaffHolidaysViewModel.HolidayAllowance = NotifyTask.Create(
_staffDataService.EmployeeHolidayAllowanceAsync(_selectedEmployee.Id));
您在这里要做的是启动EmployeeHolidayAllowanceSync
,然后用NotifyTask
包装其任务。这是同步完成的,因此可以在属性设置器中完成
然后,还需要更新数据绑定。最明显的是Result
,它最终将保存EmployeeHolidayaAllowanceAsync
的结果(在EmployeeHolidayaAllowanceAsync
完成之前,它将返回一个默认值)。还有IsNotCompleted
和IsFaulted
,您希望使用它们向用户指示数据尚未到达或存在错误。我的理解是这是不可能的。绑定机制要求属性在该时刻直接返回值。不过,有一些可用的模式可以间接地处理它。请参阅Stephen Cleary的MSDN帖子: