title: Wait cursor in MVVM
body: <p>Need a wait cursor for long operations.<br>
  Mouse.OverrideCursor works in the ViewModel but not really an MVVM pattern.<br>
  <strong>I have an IsBusy property - how do I get wait cursor in the View?</strong>  </p>
  
  <p>This kind of works<br>
  But I only get the wait cursor over the button<br>
  I want the wait cursor on the whole Window 
  I hacked in Mouse.OverrideCursor = Cursor.Wait in the converter but it feels hacky 
  Is there a better way to do this? </p>
  
  <pre><code>&lt;Window x:Class="WaitCursor.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          xmlns:local="clr-namespace:WaitCursor"
          mc:Ignorable="d"
          Title="MainWindow" Height="350" Width="525"&gt;
      &lt;Window.Resources&gt;
          &lt;BooleanToVisibilityConverter x:Key="BVC"/&gt;
          &lt;local:ViewModel x:Key="ViewModel"/&gt;
          &lt;local:BusyMouseConverter x:Key="BusyToCursorConverter"/&gt;
      &lt;/Window.Resources&gt;
      &lt;Window.Cursor&gt;
          &lt;Binding Path="IsBusy" Converter="{StaticResource BusyToCursorConverter}"/&gt;
      &lt;/Window.Cursor&gt;
      &lt;Grid DataContext="{StaticResource ViewModel}"&gt;
          &lt;Button  Content="Search" VerticalAlignment="Top"  Command="{Binding SearchCommand}" Margin="2,0,2,2"
                   Cursor="{Binding Path=IsBusy, Converter={StaticResource BusyToCursorConverter}}"/&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <hr>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Data;
  using System.Windows.Documents;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  using System.Windows.Navigation;
  using System.Windows.Shapes;
  using System.Windows.Markup;
  
  namespace WaitCursor
  {
      /// &lt;summary&gt;
      /// Interaction logic for MainWindow.xaml
      /// &lt;/summary&gt;
      public partial class MainWindow : Window
      {
          public MainWindow()
          {
              InitializeComponent();
          }
      }
      [ValueConversion(typeof(bool), typeof(Cursors))]
      public class BusyMouseConverter : MarkupExtension, IValueConverter
      {
          public BusyMouseConverter()
          {
          }
  
          public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
          {
              if (value is bool)
              {
                  if ((bool)value)
                  {
                      Mouse.OverrideCursor = Cursors.Wait;  // this works but it feels hacky
                      return Cursors.Wait;
                  }
                  else
                  {
                      Mouse.OverrideCursor = null;
                      return null;
                  }
              }
  
              return null;
          }
  
          public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
          {
              if (value is Cursors)
              {
                  if (value == Cursors.Wait)
                      return true;
                  else
                      return false;
              }
  
              return null;
          }
  
          public override object ProvideValue(IServiceProvider serviceProvider)
          {
              return instance;
          }
  
          private static BusyMouseConverter instance = new BusyMouseConverter();
  
      }
  }
  </code></pre>
  
  <hr>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Input;
  using System.ComponentModel;
  using System.Diagnostics;
  
  
  namespace WaitCursor
  {
      public class ViewModelBase : INotifyPropertyChanged
      {
          public event PropertyChangedEventHandler PropertyChanged;
          protected void NotifyPropertyChanged(string propertyName)
          {
              if (PropertyChanged != null)
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
              }
          }
      }
  
      class ViewModel : ViewModelBase
      {
          private ICommand _SearchCommand;
          public ICommand SearchCommand
          {
              get
              {
                  if (_SearchCommand == null)
                  {
                      _SearchCommand = new RelayCommand(param =&gt; this.Search(), null);
                  }
                  return _SearchCommand;
              }
          }
          private bool isBusy = false;
          public bool IsBusy
          {
              get { return isBusy; }
              set
              {
                  if (isBusy == value)
                      return;
                  isBusy = value;
                  NotifyPropertyChanged("IsBusy");
                  NotifyPropertyChanged("Cursor");
              }
          }
          private async void Search()
          {
              IsBusy = true;
              //UIServices.SetBusyState();
              //Mouse.OverrideCursor = Cursors.Wait;
              await Task.Delay(5000);
              Debug.WriteLine("Search");
              //Mouse.OverrideCursor = null;
              IsBusy = false;
          }
      }
      public class RelayCommand : ICommand
      {
          public RelayCommand(Action&lt;object&gt; execute) : this(execute, null)
          {
          }
          public RelayCommand(Action&lt;object&gt; execute, Predicate&lt;object&gt; canExecute)
          {
              if (execute == null)
                  throw new ArgumentNullException("execute");
              _execute = execute;
              _canExecute = canExecute;
          }
          public bool CanExecute(object parameter)
          {
              return _canExecute == null ? true : _canExecute(parameter);
          }
          public event EventHandler CanExecuteChanged
          {
              add { CommandManager.RequerySuggested += value; }
              remove { CommandManager.RequerySuggested -= value; }
          }
          public void Execute(object parameter)
          {
              _execute(parameter);
          }
          private readonly Action&lt;object&gt; _execute;
          private readonly Predicate&lt;object&gt; _canExecute;
      }
  }
  </code></pre>