A.D.
A.D.

Reputation: 1116

UI thread not refreshing as expected into a WPF form

I have an issue with UI refresh in this RelayCommand:

private RelayCommand _DeleteReferenceCommand;
public RelayCommand DeleteReferenceCommand
{
    get
    {
        return _DeleteReferenceCommand ?? (_DeleteReferenceCommand = new RelayCommand(
            () =>
              {
                 //the 2 next lines trigger properties that will modify some components Visibility on the view
                 ReferencesGridWithPicsUC.TextReplacingGridView = "Deleting the reference. Please wait...";
                 ReferencesGridWithPicsUC.GridViewVisibility = false;
                System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor; // mouse cursor change


               //using multi-threading so that UI updates while a long process takes place in the background
               Task.Run(() =>
               {
                  Application.Current.Dispatcher.Invoke((new Action(() =>
                  {
                    System.Threading.Thread.Sleep(3000); // simulates a long process
                    ReferencesGridWithPicsUC.GridViewVisibility = true; // Sets the UI controls visibility back to previous state
                    System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Hand; // Mouse cursor back to previous value
                 }
              )));
           }
       );
     },
     () => { return ReferencesGridWithPicsUC.SelectedReference != null; }
    ));
  }
}

Concretely, when I start the app and run this code for the forst time, it works as expected (mouse cursor and controls are updated as expected before the Sleep(3000) and back to normal afterwards. When the code is executed again, I can see that the property is correctly updated GridViewVisibility . But the UI does not refresh anymore: the control visibility triggered by GridViewVisibility changes is not updated. On the other hand the mouse cursor keeps updating as expected....

If someone can solve this bloody puzzle, I ll be in your debt ;)

Upvotes: 2

Views: 187

Answers (1)

user6996876
user6996876

Reputation:

You have to invoke the Dispatcher only for updating the UI.

Use Task.Run for the background task.

await Task.Run(() =>
    {
        Thread.Sleep(3000);
    });

in an async delegate

new RelayCommand(
          async () =>
          {

After that, you'll be back in the UI thread, so the Dispatcher is no longer needed.

Upvotes: 4

Related Questions