0

I'm curious what the most elegant way to implement the following is.

I have a Background Worker that loads up a progress bar UI, and updates it's status as it runs a query. While this is happening, the main application is disabled in the background so that users can't touch it. Once it completes, the progress bar ends and and main application UI is enabled again. My question is, where is the best way to do this work in the UI thread.

Right now, I pass in an instance of the MainWindow (main ui) to the Background Worker and do the enabling/disabling in there:

    public static void RunQuery(WorkerArguments workerArgs, MainWindow mw)
    {
        BackgroundWorkerInitialize();       // initialize BackgroundWorker events

        mainWindow = mw;
        stopWatch = new Stopwatch();        // create a new stopwatch
        queryLoading = new QueryLoading();  // create a new QueryLoading screen
        queryLoading.Owner = mainWindow;    // set queryLoading owner to MainWindow (results in QueryLoading UI loading in the center of mainUI)

        mainWindow.SetIsEnabled(false);     // disable the main UI 
        queryLoading.Show();                // show the query loading screen
        backgroundWorker.RunWorkerAsync(workerArgs);    // do the work
    }

    private static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // We need to check e.Error to find out if any exceptions were thrown in Do_Work
        if (e.Error != null)
        {
            ExceptionHandler.ExceptionHandlingUtility.DisplayExceptionUI(e.Error.ToString(), mainWindow);
        }

        else
        {        
            ObservableCollection<Client> clients = (ObservableCollection<Client>)e.Result;  // cast result to ObvservableCollection<Client>

            queryLoading.Close();           // close loading ui
            mainWindow.SetIsEnabled(true);  // enable the main UI
            stopWatch = null;
            mainWindow.DisplaySearchResults(clients); // display our results
            BackgroundWorkerCleanup();      // cleanup background worker events
            }
    }

Is there a better or cleaner way to do this, it doesn't feel "right" to me. I was thinking of perhaps sending my ViewModel as a parameter instead of the MainWindow, and having methods in my viewModel that will enable/disable the app. I'll need a reference to the viewModel anyways so that I can pass back the clients returned from the search query.

The SetIsEnabled method is a method I created in the MainWindow.xaml.cs, which looking back now was probably unnecessarily redundant.

    /**
     * SetIsEnabled
     *  Sets the IsEnabled property of main UI
     * Args:
     *  isEnabled - boolean value to set isEnabled
     **/
    public void SetIsEnabled(bool isEnabled)
    {
        this.IsEnabled = isEnabled;
    }
Talen Kylon
  • 1,908
  • 7
  • 32
  • 60
  • That is why `IsEnabled` is a property so it can be bound. Not sure where that `SetIsEnabled` comes from. If that is some home-grown function, then you either change it to dependency property or look for "how to call View from ViewModel" questions. – Euphoric Nov 25 '16 at 14:33
  • @Euphoric Interesting that the IsEnabled can be bound, I hadn't even thought of that. I'll look into it. The SetIsEnabled method is something I created in the MainWindow.xaml.cs, I added in a brief explanation. – Talen Kylon Nov 25 '16 at 14:36

2 Answers2

2

As suggested by others: exposing a property on the ViewModel and binding the IsEnabled to it, is a clean way of doing this.

It is also possible, if the control that you want to disable supports Commands, to implement a Command on the ViewModel that returns a 'false' when CanExecute is called when the background worker is busy: How to use the CanExecute Method from ICommand on WPF

Community
  • 1
  • 1
Emond
  • 50,210
  • 11
  • 84
  • 115
1

I think you want to create the new Boolean property in your view model, bind that bool property in you XAML file property of IsEnabled. Set the true false based on your condition in your view model don't want to pass the View.

Poovizhi
  • 89
  • 9