Because some people were having trouble understanding how to use my original
WPF progress bar code, I thought I'd post an updated, easier to use version.
The problems people were having pretty much all centered around not understanding how to run their code in a background thread. My updated version handles this for you.
First, please have a look at the original post, as you will need some of the code from there:
WPF Progress Bars
The XAML and IProgressContext code is still the same, but here is an updated partial class for the progress dialog, along with a delegate definition that it requires:
public delegate void ProgressWorkerDelegate(IProgressContext progressContext);
public partial class ProgressDialog : Window, IProgressContext
{
private bool canceled = false;
private ProgressWorkerDelegate workDelegate = null;
public bool Canceled
{
get { return canceled; }
}
public ProgressDialog() : this(null)
{
}
public ProgressDialog(ProgressWorkerDelegate workDelegate)
: this(workDelegate, false)
{
}
public ProgressDialog(ProgressWorkerDelegate workDelegate, bool startInBackground)
{
this.workDelegate = workDelegate;
InitializeComponent();
CancelButton.Click += new RoutedEventHandler(CancelButton_Click);
if (workDelegate != null)
{
if (startInBackground)
{
new Thread(new ThreadStart(StartWork)).Start();
}
else
{
StartWork();
}
}
}
private void StartWork()
{
workDelegate(this);
}
void CancelButton_Click(object sender, RoutedEventArgs e)
{
canceled = true;
CancelButton.IsEnabled = false;
}
public void UpdateProgress(double progress)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background,
(SendOrPostCallback)delegate { Progress.SetValue(ProgressBar.ValueProperty, progress); }, null);
}
public void UpdateStatus(string status)
{
Dispatcher.BeginInvoke(DispatcherPriority.Background,
(SendOrPostCallback)delegate { StatusText.SetValue(TextBlock.TextProperty, status); }, null);
}
public void Finish()
{
Dispatcher.BeginInvoke(DispatcherPriority.Background,
(SendOrPostCallback)delegate { Close(); }, null);
}
}
The key difference is that you can now pass the dialog a delegate that will be used to do your work, and can have it automatically get run in the background.
To use it, do something like this:
ProgressDialog progressDialog = new ProgressDialog(MyWorkFunction, true);
progressDialog.ShowDialog();
Note that I am using ShowDialog() above to keep the operation modal. If you want the rest of your UI to still accept input, use Show() instead.
Your function to actually do the work would look something like this:
void MyWorkFunction(IProgressContext progressContext)
{
for (int i = 0; i < 100; i++)
{
if (myProgressContext.Canceled)
break;
progressContext.UpdateProgress((double)i / 100.0);
progressContext.UpdateStatus("Doing Step " + i);
}
progressContext.Finish();
}