views:

235

answers:

1

Hi,

I bind a command to a button through command property and doing a command binding in the page it is placed. In execute method I create an instance of a class that contains the background worker and I start it (this is a long task). The background worker (bw) class contains a variable isRunning that it is set to true before DoWork method is executed and to false when RunWorkerCompleted is executed. So from the code behind of the page where button is placed, in CanExecute method I set e.canExecute to true if bw is no running (isRunning = false), and e.canExecute to false if isRunning = true.

WHen I press the button, it launch bw process for a long time and the button gets disabled. Ok this is correct, but when background worker (bw) finishes, the button doesn't returns to enabled until I press it again. When it is disabled and I press (when bw is finished) it gets enabled. Why the button is not returning automatically to enabled at the end of the bw?

my code snippet:

<Page  x:Class="GParts.Pages.MyPage" 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
   xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;
    assembly=PresentationFramework.Aero"            
    xmlns:local="clr-namespace:GParts"      
    Loaded="Page_Loaded"  
    Unloaded="Page_Unloaded" 
    Height="Auto">

  <Page.CommandBindings>
    <CommandBinding Command="{x:Static local:Pages.MyPage.rcmd}"
               Executed="CommandBinding_Executed"
               CanExecute="CommandBinding_CanExecute"/>
  </Page.CommandBindings>

   <...>
   <Button Command="{x:Static local:Pages.MyPage.rcmd}" />

<...>
</Page>

The code behind of the page:

 namespace GParts.Pages
 {

   public partial class MyPage : Page
   {

    public static RoutedCommand rcmd = new RoutedCommand();

    private cBgWorker bw;

    <...>

    // ExecutedRoutedEventHandler for the custom button remove all command.
    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {

            // get an isntance of the background worker class
            bw = new cBgWorker();

            // start the long task
            bw.StartTask();

    }

    // CanExecuteRoutedEventHandler for the custom button remove all command.
    private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        // bw is the instance of background worker class
        if (bw == null)
        {
            e.CanExecute = true;
        }
        else
        {
            e.CanExecute = !bw.isRunning;// isRunning indicates if bw is
                                         //executing now         
        }
    }

    <...>

} // end class
} // end namespace
+4  A: 

When your BackgroundWorker completes, call CommandManager.InvalidateRequerySuggested();

By default, Commands are only requeried occasionally by WPF. Otherwise, there would be a huge amount of overhead in constantly calling "CanExecute" on every ICommand implementation. Calling the above method forces the CommandManager to update immediately.

This will force the Commands to re-enable/disable appropriately.

Reed Copsey