Reputation: 13306
We have a WPF app (actually a VSTO WPF app). On certain controls there are multiple elements which, when clicked, load data from a web service and update the UI. Right now, we carry out these web requests synchronously, blocking the UI thread until the response comes back. This prevents the user clicking around the app while the data is loading, potentially putting it into an invalid state to handle the data when it is returned.
Of course the app becomes unresponsive if the request takes a long time. Ideally, we'd like to have the cancel button active during this time, but nothing else. Is there a clever way of doing this, or will we have to switch the requests to execute asynchronously using backgroundworker and write something that disables all the controls apart from the cancel button while a request is in progress?
edit: for actions we already expect to be long running (downloading a file etc.) we pop up a progress dialog window. The case in point is when you expect the action to be pretty fast (a couple of seconds at most) but occasionally take longer. In those circumstances, flashing up a whole window for a moment is a bit too distracting.
Upvotes: 4
Views: 5731
Reputation: 11287
The Silverlight Toolkit has a BusyIndicator control. The toolkit is open source so you might easily be able to port it to WPF.
It disables and greys out everything in the area that it's assigned to when setting its IsBusy
property to true either in code or by binding it to a model. Usage is as follows:
<ctl:BusyIndicator>
<StackPanel x:Name="myDataArea">
<Button Content="Load Data" />
<DataGrid x:Name="myDataGrid" />
</StackPanel>
</ctl:BusyIndicator>
Upvotes: 1
Reputation: 96702
Your clickable controls should be bound to commands, and the commands should have CanBeExecuted
return false when a background task is in progress. If you do this, the controls bound to those commands will automatically disable and enable themselves.
You can avoid duplicating a lot of code by creating a command class that implements the background-task-in-progress check, and then deriving all of your commands (except the cancel command, of course) from this class.
Upvotes: 4
Reputation: 2618
One way would be to put a translucent canvas over the parts of the UI which are not accessible while waiting for the response and in the center put a message with a cancel button.
Upvotes: 1
Reputation: 137108
I can't think of easy way other than disabling all controls except for "cancel".
Having said that, it might give a better user experienced if you displayed a "working" or progress dialog with just a cancel button.
You could use this dailog to display useful information about the progress of the web requests and any error messages that might come back.
Upvotes: 0
Reputation: 245389
While you make your Asynchronous request on a seperate thread, show a Modal Dialog box with a Cancel button (and maybe a progress bar or some other activity indicator).
That way the user can't interact with the underlying UI and they still get feedback that something is happening...and the ability to cancel it.
Upvotes: 1