[英]MVVM and async properties
I have a ViewModel with the following property 我有一个具有以下属性的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();
}
}
The line 线
StaffHolidaysViewModel.HolidayAllowance = _staffDataService.EmployeeHolidayAllowance(_selectedEmployee.Id);
Contains a call to a method that I'd like to make asynchronous. 包含对我想进行异步处理的方法的调用。 I don't know how I can do this as SelectedEmployee is a bound property.
我不知道该怎么做,因为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>
Since it's a property, I can't make its type Task<Employee>
由于它是一个属性,因此无法使其类型为
Task<Employee>
What's the recommended approach to async bound MVVM properties? 异步绑定MVVM属性的推荐方法是什么? Or is it just not possible?
还是只是不可能?
it's technically not the idea approach to have a property perform Asynchronous Tasks as they need to be returning a value. 从技术上讲,让属性执行异步任务不是想法方法,因为它们需要返回值。
Why? 为什么? let's look at it from another point of view:
让我们从另一个角度来看它:
Asynchronous means that the UI thread will not stop (UI won't hang while processing) while the main processing thread would wait for the operation to finish and get the results (considering you're wana be using an await
). 异步意味着UI线程将不会停止(UI在处理时不会挂起),而主处理线程将等待操作完成并获得结果(考虑到您正在使用
await
)。
When you define a binding, the UI is directly dependant on the property for data which is using await that means the UI will have to wait (which cannot happen with async
operations) and hence properties can't be made async
and because of which you can't use await
. 当您定义绑定时,UI直接依赖于使用await的数据的属性,这意味着UI必须等待(
async
操作无法发生),因此无法使属性async
,因此您不能使用await
。
What all work arounds I have used uptil now: 我到目前为止一直使用的所有变通方法是:
.Result
. .Result
的异步Task返回方法的属性。 I have tried it, it doesn't really provide with the best outputs. IAsyncOperation<>
instead of Task<>
. IAsyncOperation<>
而不是Task<>
。 This will give you the advantage of calling the the .GetResults()
method which will get you the results and will not freeze your UI thread. .GetResults()
方法的优势,该方法将为您提供结果,并且不会冻结UI线程。 More information on it here . Task<>
. Task<>
。 I perform all my operations there and verify results. RaisePropertyChanged
. RaisePropertyChanged
。 This ways I can handle other view processing or intermediate loading screens as well without having to be limited with not being able to stop the processing thread. Use either of the three methods I defined on top. 使用我在上面定义的三种方法之一。 they're all good.
他们都很好。 below are the summary points for use cases considering as an example getting a score form server of a game:
以下是一些用例的要点,以获取游戏的得分表服务器为例:
IAsyncOperation<>
when you don't want to stop any threads and just define the source of the data for the property. IAsyncOperation<>
。 The Code processing will not stop or wait for the process to get the results. Task<>
returning method if you want the code to wait until the task has been completed to perform other operations on a result. Task<>
返回方法。 eg: you want to convert the integer value to a percentage once the score is calculated. .Result
but it hasn't worked for me ever. .Result
但它对我从未奏效。 If there is anything else feel free to mention in the comments 如果还有其他意见,请在评论中提及
Contains a call to a method that I'd like to make asynchronous.
包含对我想进行异步处理的方法的调用。
I have an article on async MVVM data binding . 我有一篇关于异步MVVM数据绑定的文章。 Essentially, what I usually do is create a data-bindable
Task
- what I call NotifyTaskCompletion
in the article, shortened to NotifyTask
in my updated library . 从本质上讲,我通常做的是建立一个数据绑定的
Task
-我称之为NotifyTaskCompletion
文章,缩短到NotifyTask
在我更新的库 。
You can use it by changing the type of StaffHolidaysViewModel.HolidayAllowance
from whatever it is (I'll call it THolidayAllowance
) to a NotifyTask<T>
wrapper (eg, NotifyTask<THolidayAllowance>
). 您可以通过将
StaffHolidaysViewModel.HolidayAllowance
的类型从它的类型(我将其称为THolidayAllowance
)更改为NotifyTask<T>
包装器(例如, NotifyTask<THolidayAllowance>
)来使用它。
Then, you can set it synchronously: 然后,您可以同步设置它:
StaffHolidaysViewModel.HolidayAllowance = NotifyTask.Create(
_staffDataService.EmployeeHolidayAllowanceAsync(_selectedEmployee.Id));
What you're doing here is starting EmployeeHolidayAllowanceAsync
and then wrapping its Task
with a NotifyTask
. 您在这里要做的是启动
EmployeeHolidayAllowanceAsync
,然后用NotifyTask
包装其Task
。 This is done synchronously, so it's possible to do this in a property setter. 这是同步完成的,因此可以在属性设置器中执行此操作。
Then, your data binding also needs to be updated. 然后,您的数据绑定也需要更新。
NotifyTask<T>
has several properties that you can use . NotifyTask<T>
具有几个可以使用的属性 。 The most obvious is Result
, which will eventually hold the result of EmployeeHolidayAllowanceAsync
(it returns a default value until EmployeeHolidayAllowanceAsync
completes). 最明显的是
Result
,它将最终保存EmployeeHolidayAllowanceAsync
的结果(它返回默认值,直到EmployeeHolidayAllowanceAsync
完成)。 There's also IsNotCompleted
and IsFaulted
, which you'll want to use to indicate to the user that the data hasn't arrived yet or that there was some error. 还有
IsNotCompleted
和IsFaulted
,您将使用它们来向用户指示数据尚未到达或存在一些错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.