Wpf之异步绑定

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

posted @ 2020-04-18 10:22  非法关键字  阅读(852)  评论(0)    收藏  举报