I am using Extended WPF Toolkit and MVVM Light libraries.
I would like to implement the WPF Toolkit busy indicator and periodically informs the user with some info (binding with BusyMessage property in the viewmodel).
However, when button 'Start' is clicked, the busy indicator (IsBusy bound to IsBusy property in viewmodel) is not shown. What I am doing wrong? Oddly enough, it works when IsBusy is set to true in the constructor of the viewmodel.
App.xaml
public partial class App : Application
{
public App()
{
DispatcherHelper.Initialize();
}
}
Window
<Window xmlns:xctk='http://schemas.xceed.com/wpf/xaml/toolkit'
DataContext='{Binding Main, Source={StaticResource Locator}}'>
<StackPanel>
<xctk:BusyIndicator IsBusy='{Binding IsBusy}'>
<xctk:BusyIndicator.BusyContentTemplate>
<DataTemplate>
<StackPanel Margin='4'>
<TextBlock Text='{Binding DataContext.BusyMessage, RelativeSource={RelativeSource AncestorType={x:Type Window}}}' />
</StackPanel>
</DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>
<Button Content='Start ...'
Command='{Binding StartCommand}'
HorizontalAlignment='Center'
VerticalAlignment='Center' />
</xctk:BusyIndicator>
Viewmodel
public class MainViewModel : ViewModelBase
{
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));
}
}
}
public RelayCommand StartCommand
{
get { return new RelayCommand(() => StartExecute()); }
}
private async void StartExecute()
{
IsBusy = true;
await Task.Run(() =>
{
//update UI from worker thread
DispatcherHelper.CheckBeginInvokeOnUI(() => BusyMessage = "Work 1 Done");
Thread.Sleep(1000);
//update UI from worker thread
DispatcherHelper.CheckBeginInvokeOnUI(() => BusyMessage = "Work 2 Done");
});
IsBusy = false;
}
public MainViewModel()
{
//Works when boolean is set to 'true' in constructor
//IsBusy = true;
}
}
That is exactly why I prefer ReactiveUI - it has "busy indicator" built into ReactiveCommand, even async one.
As for your problem, I would say that your RaisePropertyChanged(nameof(_isBusy));
is wrong and it should be RaisePropertyChanged(nameof(IsBusy)); // name of the public property
Also, depending on your RaisePropertyChanged implementation, you can propably leave the argument empty and just use RaisePropertyChanged();