Consider this example:
Private Sub Button_Click(
sender As Button, e As RoutedEventArgs) Handles btn.Click
sender.IsEnabled = False
Thread.Sleep(5000)
sender.IsEnabled = True
End Sub
In my scenario the Button_Click
is a command delegate in the VM, and the Thread.Sleep
is some long-running process (about 2-10 seconds).
I want, that when the user calls the command, it should immediately update the UI disabling the button so the user cannot execute it while it's running, then execute that operation, then, when operation completed, unblock the button.
I tried wrapping the middle line like the following:
Dispatcher.BeginInvoke(Sub() Thread.Sleep(5000))
But it didn't do the job.
What's the best way to do it?
The button click event is handled by the UI thread, hence when you invoke
thread.sleep
you make the UI thread sleep, and you see no changes until the method ends.Therefore you need to run the process on a new thread, and when the process ends, make the UI changes using the dispatcher.
For example:
The MVVM way you'll bind your button
IsEnabled
property to a boolean property in your viewModel, and update the VM propety instead on the button directly.Bind the button enabled property to a property in your VM (say ProcessComplete).
Use the button onclick event to trigger a method in your VM that starts up your long winded process. Keep the ProcessComplete False whilst the process is running and then set it True when it completes.
Instead of creating a thread of your own you can also use the BackgroundWorker Control. By calling the Method "RunWorkerAsync" the DoWork Event get's called in another Thread.
By Calling the Method "CancelAsync" form your UI thread you can set the Backgroundworker to "Cancellation Pending" (Property of the Control "CancellationPending" is then true). In your long running background thread you can check for that property (e.g. if you have a loop: exit the loop as soon as CancellationPending is true). This is a quite nice feature to safely abort the thread.
In addition with the Backgroundworker you can also report the progress of the thread (e.g. for use in a ProgressBar)
Example:
In reference to your question the code should be: