This is a general purpose progress dialog. It takes a background worker object as a parameter.
Here is the Xaml for the dialog:
<Window x:Class="AsyncMessageDlg"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AsyncMessageDlg" Height="314" Width="750"
WindowStartupLocation="CenterOwner"
Closing="Window_Closing" Loaded="Window_Loaded">
<Grid>
<Ellipse Fill="Azure" Height="56" Margin="0,27,120,0" Name="ellipse2"
Stroke="Beige" VerticalAlignment="Top" HorizontalAlignment="Right" Width="82" />
<Ellipse Fill="Azure" Height="56" Margin="120,0,0,20" Name="ellipse1"
Stroke="Beige" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="82" />
<TextBox Margin="12,35,12,63" Name="textBox" IsReadOnly="True"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" />
<Button Height="23" Margin="560,0,0,6" VerticalAlignment="Bottom"
Name="butOK" HorizontalAlignment="Left" Width="75" IsDefault="True" Click="butOK_Click">_Ok</Button>
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,6"
Name="butCancel" VerticalAlignment="Bottom" Width="75" IsCancel="True" Click="butCancel_Click">_Cancel</Button>
<Label Height="28" Margin="12,7,12,0" Name="label"
VerticalAlignment="Top">Label</Label>
<ProgressBar Height="16" Margin="120,0,181,41" Name="progressBar"
VerticalAlignment="Bottom" Visibility="Hidden" />
<TextBlock Height="16" HorizontalAlignment="Right" Margin="0,0,144,41"
Name="tbProgressPercent" Text="0%" TextAlignment="Right" VerticalAlignment="Bottom" Width="31" Visibility="Hidden" />
</Grid>
</Window>
The dialog takes a string for the dialog title and a string for the label above the output text window. When the background worker task sends a progress update it tries to convert the UserState object passed in the event to a string which is added to the output window.
Here is the code for the dialog:
public partial class AsyncMessageDlg : Window
{
BackgroundWorker m_WorkerThread = null;
bool m_Completed = false;
public AsyncMessageDlg(
string textBoxTitle,
string dlgTitle,
BackgroundWorker bw)
{
Debug.Assert(bw != null);
InitializeComponent();
this.Title = dlgTitle;
this.label.Content = textBoxTitle;
m_Completed = false;
InitialiseBackgrounWorker(bw);
}
private void InitialiseBackgrounWorker(BackgroundWorker bw)
{
Debug.Assert(bw != null);
Debug.Assert(bw.WorkerSupportsCancellation);
this.m_WorkerThread = bw;
//if (m_WorkerThread.WorkerReportsProgress)
butCancel.IsEnabled = m_WorkerThread.WorkerSupportsCancellation;
butOK.IsEnabled = false;
tbProgressPercent.Visibility = Visibility.Visible;
progressBar.Visibility = Visibility.Visible;
m_WorkerThread.ProgressChanged += new
ProgressChangedEventHandler(
m_WorkerThread_ProgressChanged);
m_WorkerThread.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(
m_WorkerThread_RunWorkerCompleted);
}
void m_WorkerThread_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
return;
m_Completed = true;
string result = e.Result as string;
if (result != null)
{
label.Content = result as string;
}
progressBar.Value = progressBar.Maximum;
tbProgressPercent.Text = "100%";
butOK.IsEnabled = true;
butCancel.IsEnabled = false;
}
void m_WorkerThread_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
Debug.Assert((e.ProgressPercentage >= 0) &&
(e.ProgressPercentage <= 100));
progressBar.Value = e.ProgressPercentage;
tbProgressPercent.Text = e.ProgressPercentage.ToString() +
"%";
if (e.UserState != null)
{
if (e.UserState is string)
{
textBox.Text += e.UserState as string;
}
else
{
textBox.Text += e.UserState.ToString();
}
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
m_WorkerThread.RunWorkerAsync();
}
private void Window_Closing(object sender, CancelEventArgs e)
{
CancelWorkerThread();
m_WorkerThread.Dispose();
}
private void butOK_Click(object sender, RoutedEventArgs e)
{
DialogResult = m_Completed;
this.Close();
}
private void butCancel_Click(object sender, RoutedEventArgs e)
{
if (!m_Completed)
{
CancelWorkerThread();
}
DialogResult = m_Completed;
}
private void CancelWorkerThread()
{
if (m_WorkerThread.IsBusy &&
m_WorkerThread.WorkerSupportsCancellation)
m_WorkerThread.CancelAsync();
}
}
Here is the code for a sample background worker
// Background worker to check out some files
internal class AsynchAddCheckOutFiles : BackgroundWorker
{
List<FileSystemInfo> m_fileSystemInfoList;
// Pass required info in through constructor, cant change it
// whilst a search is underway
public AsynchAddCheckOutFiles(ref List<FileSystemInfo> fileSystemInfoList) :
base()
{
this.m_fileSystemInfoList = fileSystemInfoList;
// Set clients refernce to null, we own the list.
fileSystemInfoList = null;
this.WorkerReportsProgress = true;
this.WorkerSupportsCancellation = true;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
bool cancelled = false;
double progress = 0;
double prevProgress = 0;
int m_NumberFiles = m_fileSystemInfoList.Count;
int count = 0;
if (!cancelled)
{
foreach (FileSystemInfo fsi in m_fileSystemInfoList)
{
if (CancellationPending)
{
cancelled = true;
break;
}
Perforce.P4CommandTransaction res =
Perforce.Instance.AddCheckOutFile(fsi);
string state = res.ToString();
++count;
// progress as a percentage
progress = (100.0 * (double)count /
(double)m_NumberFiles) + 0.5;
// Report every 1% of progress
if ((progress - prevProgress) > 1.0)
{
ReportProgress((int)(progress), state);
prevProgress = progress;
}
}
}
e.Cancel = cancelled;
}
}