Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generally Preferred Method for a 'Wait' Screen using MVVM and Silverlight

I'm moving along on a small proof of concept application. This is mostly to beef up my MVVM skills within Silverlight. I came across an interesting problem today that I could not figure how to solve the MVVM way. I wasn't successful finding anything relevant during search either.

So on to the problem, I have a simple business type application with a database back end. I have a login view and a view model attached that will perform the login and report success or failure. No problem. What I haven't been happy with just yet is a way to report a wait screen to the user. So given my login screen, the user click Login and there's a delay of a couple of seconds while the database chatting is done. I'd like to report this and disable any interaction until the call is completed.

I had a couple of ideas. First, bind the Cursor property to the viewmodel and the VM can set an IsBusy property to true. Problem with this is that I cannot seem to bind to Cursor for the UserControl (Visual Studio says AG_E_RUNTIME_MANAGED_UNKNOWN_ERROR).

Second idea is to have a wait screen. You know, the little gears turning or whatever animation you want. And that's fine, but it's not real clear to me how I could make the view toggle this through the model through the Xaml. I know I could definitely hook up events and handle this in code. Maybe that's the way to go? Seems to against the MVVM grain just a bit.

Would be interested in more ideas on how to handle this.

Thank you.

like image 484
billb Avatar asked Jul 05 '09 17:07

billb


2 Answers

I think others might be "overthinking" this one...

I would recommend using the BusyIndicator in the Silverlight toolkit.

Simple XAML:

<toolkit:BusyIndicator Name="busyBoy" IsBusy="true" BusyContent="Fetching Data..." Margin="6,248,0,0" />
like image 111
Lucas B Avatar answered Nov 02 '22 12:11

Lucas B


We've ended up using a service for processing long running requests. The service takes the workload as a delegate, and then passes it off to a BackgroundWorker, while also opening our "Please wait" view.

This works well as it allows us to control long running processes across all our ViewModels in the same way, with a fairly simple interface.

You could have events coming from the ViewModel update the View when you need a delay, but then you need to have this code in all your ViewModels, and not in a single class that can be maintained more easily.

EDIT A service is just a class that's registered within your IOC container, and can be used by your ViewModels.

public interface IProcessingService
{
    void Process(Action<BackgroundWorker> action);
    void Process(Action<BackgroundWorker> action, 
        Action<RunWorkerCompletedEventArgs> finish);
}

Using this your ViewModel could implement something like this.

{
    var processingService = container.Resolve<IProcessingService>();
    processingService.Process(worker => 
    {
        worker.ReportProgress(0, "Please wait...");
        // Do work here
        worker.ReportProgress(50);
        // Do more work
        worker.ReportProgress(100);
    });
}

This way all your code for displaying the progress notification is in the class that implements IProcessingService and your views remain free of any code that directly controls a view or any UI elements.

like image 1
Cameron MacFarland Avatar answered Nov 02 '22 13:11

Cameron MacFarland