Reputation: 2973
I have a number of time-consuming tasks in my program such as loading large DataGrids, updating multiple Databases etc. etc. What I would like to do is display a "Please wait..." MessageBox or Form whilst these tasks are running. I've had a look at BackgroundWorker but can't seem to get my head round it.
To minimize the amount of code needed, ideally I would like a method that can be called from anywhere as this will be used in many places in my program, though I know that might be tricky.
public CompanyManagement()
{
InitializeComponent();
FillDataGrid(); // This method takes all the time
}
private void FillDataGrid()
{
//Display a message until this has completed
var _cDS = new CompanyDataService();
var Companies = new ObservableCollection<CompanyModel>();
Companies = _cDS.HandleCompanySelect();
CompanyICollectionView = CollectionViewSource.GetDefaultView(Companies);
CompanyICollectionView.SortDescriptions.Add(new SortDescription("CompanyName", ListSortDirection.Ascending));
DataContext = this;
cancelButton.Visibility = Visibility.Hidden;
if (compNameRad.IsChecked == false &&
compTownRad.IsChecked == false &&
compPcodeRad.IsChecked == false)
{
searchBox.IsEnabled = false;
}
dataGrid.SelectedIndex = 0;
}
Is there a way to have a completely separate method to call? I guess this would be hard as there is no way then for that method to know when the tasks have been completed, unless it is surrounding the code to be checked.
EDIT: using Matthew's example;
public CompanyManagement()
{
InitializeComponent();
var wait = new PleaseWait("My title", "My Message", () => FillDataGrid());
wait.ShowDialog();
}
Upvotes: 1
Views: 438
Reputation: 109617
Here's an approach you can take if you're using .Net 4.5 or later (so you can use await
and async
.
1) Create a Window
class called "PleaseWait" and add to it a Label
called label
.
2) Add the following field and constructor to the class:
readonly Action _action;
public PleaseWait(string title, string message, Action action)
{
_action = action;
InitializeComponent();
this.Title = title;
this.label.Content = message;
}
3) Handle the window's loaded
event and name the handler loaded
, then implement it as follows:
private async void loaded(object sender, RoutedEventArgs e)
{
await Task.Run(() => _action());
this.Close();
}
Now when you want to show a "please wait" message, create a PleaseWait
object passing to it the title, the message and an Action
that encapsulates the code you want to run. For example:
private void button_Click(object sender, RoutedEventArgs e)
{
var wait = new PleaseWait("My title", "My Message", myLongRunningMethod);
wait.ShowDialog();
}
private void myLongRunningMethod()
{
Thread.Sleep(5000);
}
Or (using a Lambda):
private void button_Click(object sender, RoutedEventArgs e)
{
var wait = new PleaseWait("My title", "My Message", () => Thread.Sleep(5000));
wait.ShowDialog();
}
This is just a basic outline. There's more work for you to do, including making the "PleaseWait" dialog look nice and disabling the user's ability to close it manually.
Upvotes: 2