使用Extended WPF Toolkit与MVVM Light时BusyIndicator异步不显示问题
解决WPF Toolkit BusyIndicator点击按钮后不显示的问题
嘿,我一眼就揪出问题所在了——你ViewModel里的RaisePropertyChanged调用传错参数啦!
你现在给RaisePropertyChanged传的是私有字段的名字(nameof(_busyMessage)、nameof(_isBusy)),但MVVM Light的这个方法需要的是公共属性的名称。UI绑定的是你的IsBusy和BusyMessage公共属性,只有当你通知这些属性的名称变化时,UI才会感知到并更新状态。
第一步:修正PropertyChanged通知
把ViewModel里的属性setter改成下面这样:
private string _busyMessage; public string BusyMessage { get { return _busyMessage; } set { if (_busyMessage != value) { _busyMessage = value; // 改成公共属性的名称,不是私有字段 RaisePropertyChanged(nameof(BusyMessage)); } } } private bool _isBusy; public bool IsBusy { get { return _isBusy; } set { if (_isBusy != value) { _isBusy = value; // 同样改成公共属性的名称 RaisePropertyChanged(nameof(IsBusy)); } } }
第二步:(可选)简化BusyContent的绑定
你当前的BusyContentTemplate绑定用了RelativeSource,其实可以简化——因为BusyIndicator的DataContext和Window是一致的,直接绑定属性名就行:
<xctk:BusyIndicator.BusyContentTemplate> <DataTemplate> <StackPanel Margin='4'> <TextBlock Text='{Binding BusyMessage}' /> </StackPanel> </DataTemplate> </xctk:BusyIndicator.BusyContentTemplate>
为什么构造函数里设置IsBusy=true能生效?
这是因为ViewModel初始化时,UI还在建立绑定关系,会自动读取一次IsBusy的初始值。但后续通过按钮命令修改属性时,必须依赖正确的PropertyChanged通知才能让UI更新状态,这就是为什么点击按钮后BusyIndicator没反应的原因。
(可选)优化异步命令写法
虽然async void在RelayCommand里能运行,但更规范的写法是用async Task,你可以把StartCommand改成这样:
public RelayCommand StartCommand { get { return new RelayCommand(async () => await StartExecute()); } } private async Task StartExecute() { IsBusy = true; await Task.Run(() => { Thread.Sleep(1000); DispatcherHelper.CheckBeginInvokeOnUI(() => BusyMessage = "Work 1 Done"); Thread.Sleep(1000); DispatcherHelper.CheckBeginInvokeOnUI(() => BusyMessage = "Work 2 Done"); }); IsBusy = false; }
这样代码更符合异步编程的最佳实践,也更容易维护。
内容的提问来源于stack exchange,提问作者BertAR
相关产品推荐
相关产品推荐

