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 |
| { |
| |
| } |
| |
| 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗