wpf中的IsAsync在某些情况下使用并不太理想, 直接上代码
public sealed class NotifyTaskCompletion<TResult> : INotifyPropertyChanged
{
public NotifyTaskCompletion(Task<TResult> task)
{
Task = task;
if (!task.IsCompleted)
{
var _ = WatchTaskAsync(task);
}
}
private async Task WatchTaskAsync(Task task)
{
try
{
await task;
}
catch
{
// ignored
}
var propertyChanged = PropertyChanged;
if (propertyChanged == null)
return;
propertyChanged(this, new PropertyChangedEventArgs("Status"));
propertyChanged(this, new PropertyChangedEventArgs("IsCompleted"));
propertyChanged(this, new PropertyChangedEventArgs("IsNotCompleted"));
if (task.IsCanceled)
{
propertyChanged(this, new PropertyChangedEventArgs("IsCanceled"));
}
else if (task.IsFaulted)
{
propertyChanged(this, new PropertyChangedEventArgs("IsFaulted"));
propertyChanged(this, new PropertyChangedEventArgs("Exception"));
propertyChanged(this, new PropertyChangedEventArgs("InnerException"));
propertyChanged(this, new PropertyChangedEventArgs("ErrorMessage"));
}
else
{
propertyChanged(this, new PropertyChangedEventArgs("IsSuccessfullyCompleted"));
propertyChanged(this, new PropertyChangedEventArgs("Result"));
}
}
public Task<TResult> Task { get; private set; }
public TResult Result =>
Task.Status == TaskStatus.RanToCompletion ?
Task.Result : default;
public TaskStatus Status => Task.Status;
public bool IsCompleted => Task.IsCompleted;
public bool IsNotCompleted => !Task.IsCompleted;
public bool IsSuccessfullyCompleted =>
Task.Status ==
TaskStatus.RanToCompletion;
public bool IsCanceled => Task.IsCanceled;
public bool IsFaulted => Task.IsFaulted;
public AggregateException Exception => Task.Exception;
public Exception InnerException =>
Exception?.InnerException;
public string ErrorMessage =>
InnerException?.Message;
public event PropertyChangedEventHandler PropertyChanged;
}
例如加载一个比较耗时的数据在加载过程中Loading
<Grid>
<DataGrid HeadersVisibility="Column" RowHeaderWidth="60" AutoGenerateColumns="False" ItemsSource="{Binding SteamData.Result}"
Background="{StaticResource RegionBrush}" GridLinesVisibility="Horizontal" CanUserAddRows="False"
SelectionUnit="FullRow" SelectionMode="Single">
<DataGrid.Columns ...>
</DataGrid>
<hc:LoadingCircle Style="{StaticResource LoadingCircleLarge}" Visibility="{Binding
SteamData.IsNotCompleted, Converter={StaticResource Boolean2VisibilityConverter}}"/>
</Grid>
原文参考
https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/march/async-programming-patterns-for-asynchronous-mvvm-applications-data-binding