Talen Kylon Talen Kylon - 12 days ago 6
C# Question

With MVVM, where should we make calls that enable or disable the UI?

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;
}

Answer

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.