title: Disable WPF buttons during longer running process, the MVVM way
body: <p>I have a WPF/MVVM app, which consists of one window with a few buttons.<br>
  Each of the buttons triggers a call to an external device (an <a href="http://www.dreamcheeky.com/thunder-missile-launcher" rel="nofollow noreferrer">USB missile launcher</a>), which takes a few seconds.</p>
  
  <p>While the device is running, the GUI is frozen.<br>
  <em>(<strong>This is okay</strong>, because the only purpose of the app is to call the USB device, and you can't do anything else anyway while the device is moving!)</em></p>
  
  <p>The only thing that's a bit ugly is that the frozen GUI still accepts additional clicks while the device is moving.<br>
  When the device still moves and I click on the same button a second time, the device immediately starts moving again as soon as the first "run" is finished.</p>
  
  <p>So I'd like to disable all the buttons in the GUI as soon as one button is clicked, and enable them again when the button's command has finished running.</p>
  
  <p>I have found a solution for this that looks MVVM-conform.<br>
  <em>(at least to me...note that I'm still a WPF/MVVM beginner!)</em></p>
  
  <p>The problem is that this solution doesn't work (as in: the buttons are not disabled) when I call the external library that communicates with the USB device.<br>
  But the actual code to disable the GUI is correct, because it <strong>does</strong> work when I replace the external library call by <code>MessageBox.Show()</code>.</p>
  
  <p>I've constructed a minimal working example that reproduces the problem (<a href="https://github.com/christianspecht/code-examples/tree/master/WpfDatabindingQuestion" rel="nofollow noreferrer">complete demo project here</a>):</p>
  
  <p>This is the view:</p>
  
  <pre><code>&lt;Window x:Class="WpfDatabindingQuestion.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="MainWindow" Height="350" Width="525"&gt;
      &lt;Grid&gt;
          &lt;StackPanel&gt;
              &lt;Button Content="MessageBox" Command="{Binding MessageCommand}" Height="50"&gt;&lt;/Button&gt;
              &lt;Button Content="Simulate external device" Command="{Binding DeviceCommand}" Height="50" Margin="0 10"&gt;&lt;/Button&gt;
          &lt;/StackPanel&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>...and this is the ViewModel <em>(using the <a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030" rel="nofollow noreferrer"><code>RelayCommand</code> from Josh Smith's MSDN article</a>)</em>:</p>
  
  <pre><code>using System.Threading;
  using System.Windows;
  using System.Windows.Input;
  
  namespace WpfDatabindingQuestion
  {
      public class MainWindowViewModel
      {
          private bool disableGui;
  
          public ICommand MessageCommand
          {
              get
              {
                  return new RelayCommand(this.ShowMessage, this.IsGuiEnabled);
              }
          }
  
          public ICommand DeviceCommand
          {
              get
              {
                  return new RelayCommand(this.CallExternalDevice, this.IsGuiEnabled);
              }
          }
  
          // here, the buttons are disabled while the MessageBox is open
          private void ShowMessage(object obj)
          {
              this.disableGui = true;
              MessageBox.Show("test");
              this.disableGui = false;
          }
  
          // here, the buttons are NOT disabled while the app pauses
          private void CallExternalDevice(object obj)
          {
              this.disableGui = true;
              // simulate call to external device (USB missile launcher),
              // which takes a few seconds and pauses the app
              Thread.Sleep(3000);
              this.disableGui = false;
          }
  
          private bool IsGuiEnabled(object obj)
          {
              return !this.disableGui;
          }
      }
  }
  </code></pre>
  
  <p>I'm suspecting that opening a <code>MessageBox</code> triggers some stuff in the background that does <strong>not</strong> happen when I just call an external library.<br>
  But I'm not able to find a solution.</p>
  
  <p>I have also tried:</p>
  
  <ul>
  <li>implementing <code>INotifyPropertyChanged</code> (and making <code>this.disableGui</code> a property, and calling <code>OnPropertyChanged</code> when changing it)</li>
  <li>calling <code>CommandManager.InvalidateRequerySuggested()</code> all over the place<br>
  <em>(I found that in several answers to similar problems here on SO)</em></li>
  </ul>
  
  <p>Any suggestions?</p>