ProgressWorker
一个带有 BackgroundWorker 包装器的 WinForms 进度条控件。
为什么?
在我的许多项目中,我使用后台工作线程来执行后台任务。有很多不同的场景可以使用它。它们都有一个共同点(或者几乎都有):我将它与进度条链接起来,以便向用户显示正在发生某些事情。
即使这是一个简单的过程,我厌倦了每次需要将其添加到项目中时都输入(或复制/粘贴)相同的代码,所以我最终将两者结合在一起。
这是什么?
所以,这就是 ProgressWorker
。它没有什么了不起的复杂性,但我发现它很有用,所以我认为我会与 CodeProject 社区分享它。
该类派生自 System.Windows.Forms.ProgressBar
,并且还是 System.ComponentModel.BackgroundWorker
的包装器。
有什么不同?
你必须有风格!
标准进度条有三种显示样式。其中两种显示递增的条,另一种 (Marquee
) 显示一个从左到右“弹跳”的条 永无止境。 后者最适用于无法量化进度但需要指示正在进行活动的情况。 为了使这种选择更加自动化,Style
属性现在只有 Block
和 Continuous
。 如果 ReportsProgress
属性为 false
,则为基本类的 Style
选择 Marquee
。 Marquee
样式的问题在于它会一直持续,即使您不希望它持续,因此只有在工作线程开始工作时才应用此样式。
没有限制
进度条通常允许您设置自己的最小值和最大值。 我已将这些固定为 0 和 100,以便它可以很好地与工作线程的 ReportProgress
配合使用,并且它们是只读的。
它价值多少?
现在 Value
属性是只读的,因为它应该只由工作线程更新。
多余的要求
不需要 Step
属性、PerformStep
和 Increment
方法,所以我已尽我所能地隐藏了它们。
继承说明
从基类继承时,您应该添加功能,而不是删除功能。 因此,并非所有内容都可以隐藏,并且无论您应用什么属性,都会显示在 intellisense 中。 微软说这是故意的,并且是正确的 OOP 方式 #(即使他们自己隐藏了很多东西!),但我真的不喜欢必须从 IWin32Window
开始并从头开始构建所有内容。
我主要在更改的内容上使用了 new
而不是 override
。 例如,重写不允许您将读/写属性转换为只读属性。 所以,在任何人因此而攻击我之前,这是故意的!
有什么新功能?
... 好吧,不多。 现有的控件和组件拥有所需的一切,这只是将它们结合到一个方便的控件中。 噢,我添加了一个 Reset
方法,它会将 Value
设置回零并在适用的情况下停止 Marquee
样式。
我更改了一些“包装”名称以删除工作线程引用。 除此之外,您会找到所有正常的进度条和后台工作线程内容,因此使用起来应该非常直观。 如果不是(或者您从未用过后台工作线程),则附加了一个演示。
代码在哪里?
在我因撰写一篇没有代码的文章而被抨击之前...! 实际上并没有什么有趣的,因为它(如前所述)只是带有包装的后台工作线程的进度条的派生。 这是一个演示的主窗体中实现的少量代码转储,以显示它的易用程度
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
progressWorker.DoWork +=
new System.ComponentModel.DoWorkEventHandler(progressWorker_DoWork);
progressWorker.ProgressChanged +=
new System.ComponentModel.ProgressChangedEventHandler(
progressWorker_ProgressChanged);
progressWorker.RunCompleted +=
new System.ComponentModel.RunWorkerCompletedEventHandler(
progressWorker_RunCompleted);
richTextBox.SelectAll();
}
private void progressWorker_DoWork(object sender,
System.ComponentModel.DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
if (progressWorker.CancellationPending)
{
e.Cancel = true;
break;
}
// simulate long operation
System.Threading.Thread.Sleep(50);
progressWorker.ReportProgress(i);
}
}
private void progressWorker_ProgressChanged(object sender,
System.ComponentModel.ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage);
}
private void progressWorker_RunCompleted(object sender,
System.ComponentModel.RunWorkerCompletedEventArgs e)
{
button.Text = "&Start ProgressWorker";
button.Enabled = true;
progressWorker.Reset();
}
private void button_Click(object sender, EventArgs e)
{
if (progressWorker.IsBusy)
{
button.Enabled = false;
progressWorker.CancelAsync();
}
else // start
{
progressWorker.RunAsync();
button.Text = "&Cancel ProgressWorker";
}
}
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
progressWorker.ReportsProgress = checkBox.Checked;
}
}
参考文献
历史
- 2009 年 3 月 13 日:初始版本。