Trying to display a "Wait" message in WPF during continuous operation

I have please wait TextBlock in my XAML, the Visibility property is bound to the IsBusy property on my ViewModel (which implements INotifyPropertyChanged ). A separate button starts a long (2-3 seconds) process, for example:

 IsBusy = true; try { // Do some long-running process } finally { IsBusy = false; } 

But please wait message never appears. I assume that the operation is performed in the user interface thread and, therefore, does not allow it to update? It works if I run the above code in a separate thread, but I do not want the user to do something during the operation - I am pleased with the interface from freeze .

How can I display please wait message? Or am I better off working on a background thread and (somehow) blocking the user interface for a while? I am using .Net 4 btw.

+4
source share
3 answers

You are right, this is not an update, because you are using the code in the same thread, so rendering does not continue until the process is complete.

You said that you are not using a background thread because you do not want the user to do anything during the operation, but it is never recommended that you completely block your application like this.

A better solution would be to bind IsEnabled your Form / Window / UserControl / etc to the IsBusy property. Then, when it becomes busy, the entire form is disabled so that the user cannot modify it without blocking the application.

+5
source

At first, the Visibility property is not bool , so if you want to bind the bool variable to it, you need to use IValueConverter , and secondly, yes, you are right, while the UI thread busy with your long-running operation will not do anything, including changing the visibility .

I suggest using the WPF Toolkit BusyIndicator waiting for the placement of your own panel, it has the IsBusy bool property.

Also froozen user interface is not user friendly, as a rule, I use this snippet

 IsBusy = true; Task.Factory.StartNew(() => { // Do work. }) .ContinueWith(t=>IsBusy=false, TaskScheduler.FromCurrentSynchronizationContext()); 

Also note to check for errors in the ContinueWith method, or you will get an exception on Task dispose

+1
source

If you run your code in a separate thread, you can access the user interface through the Dispatcher.BeginInvoke Method .

 if (!YOURCONTROL.Dispatcher.CheckAccess()) { YOURCONTROL.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate() { //do something with the control/form/... })); } else { //update your control } 
0
source

All Articles