Download source files
Download demo project
Introduction
This article came into being because of a long and frustrating search into what I thought was a simple thing to find. But doesn't it always start off that way? All I wanted was a simple way to add a standalone ProgressBar to a particular class that runs a process of varying, and sometimes lengthy times. Could not use the
ProgressBar
in the Windows Form ToolBox and get a good result. I would have had to code most of the project in the Main Form and that's just wrong on so many levels.
Searched for quite a while and found an excellent article that offered a possible solution. The article is entitled: "Dealing with Progressive Operations" by _Erik_. It had the solution I was looking for, but way too complicated for the simple project I was working on. Needed something less cumbersome, and yes probably not entirely OOP as I didn't want to get involved in interfaces. The code in his article is great for larger, more complex projects, just not this tiny one. It would have looked very lopsided as a huge part of the total code of the project would have dealt with the "simple issue" of generating a ProgressBar in a class that is not a part of the Main Form.
Just a quick side note: I plan on using the contents of Erik's article on larger scale projects as it is ideal for such.
The Problem to Solve
Create a simple, flexible, standalone ProgressBar
that can be added to any class with relative ease.
Overview
I've attempted to make this as much of a plug-and-play type project as I could. After all, that is really what I was looking for in the first place. So, I've set it up with the six files that make it work. If you like, you can skip to the end of this article and just try following the directions for inserting the StandAloneProgressBar into your project. I've tried it on a couple of different projects just to make sure the directions work. Of course I can't visualize every variance, so I'm counting on you to make any necessary adjustments to the code you require. If you think of any changes I can make to this article that will make it better, please let me know. By the way, you can make it even more complex by adding a second ProgressBar control and more Labels.
I've included a tiny demo project that doesn't do anything more than go to three Websites and access their RSS Feed Page lists. I added the StandAloneProgressBar
Form to the project to display a ProgressBar while the program is accessing the different sites. In my demo, I visit three different sites because my PC and connection are so fast that I could never see the ProgressBar for more than a couple of seconds, otherwise one website would have been more than enough. By the way, the demo includes a really useful example of Linq to XML, if you are interested in that subject.
Basically, this comes down to adding the Form for the StandAloneProgressBar
and inserting the contents of three text files into the proper places in your project.
Using the Code
File descriptions
StandAloneProgressBar.cs
- Windows Form class that is the ProgressBar to be used by other classes. Of course it includes the two attendant files: StandAloneProgressBar.Designer.cs
StandAloneProgressBar.resx
Property and Event Declarations.txt
- contains the text add-ins for the Public Properties and Event Declarations. InitialValues.txt
- Contains all the needed variable initializers and calls the start event for our ProgressBar.StartTheProgressBar.txt
- Instantiates our ProgressBar and makes the call to it.
StandAloneProgressBar.cs
This is the Windows Form class that we will be calling from within our current application. The image of it is at the beginning of this article. It is a very simple form consisting of two Labels
and a ProgressBar
control. That's all there is to the form.
The code that follows is all we need to make the events work. This contains the actual code of the three events that we declared in the class that will be using the StandAloneProgressBar. Eric really did a sublime job.
public partial class StandAloneProgressBar : Form
{
public StandAloneProgressBar()
{
InitializeComponent();
RSSFeed myDemo = new RSSFeed();
myDemo.OperationStart += (sender, e) =>
{
lblMainTitle.Text = myDemo.MainTitle;
lblSubTitle.Text = myDemo.SubTitle;
pgbMainBar.Maximum = myDemo.TotalSteps;
pgbMainBar.Value = myDemo.CurrentProgress;
Refresh();
};
myDemo.OperationProgress += (sender, e) =>
{
lblSubTitle.Text = "Visiting the RSS Feed page for " + myDemo.SubTitle;
pgbMainBar.Value = myDemo.CurrentProgress;
Application.DoEvents();
};
myDemo.OperationEnd += (sender, e) => Close();
Shown += (sender, e) => myDemo.GetRSSFeed();
}
}
Property and Event Declarations.txt
This Text file contains all the Public Properties and Event Declarations. Of special interest is the Public Property CurrentProgress
. It's written this way so as to allow flexibility in the code of the calling class without the hassle of editing it every time you use it in new class.
#region Public Properties
public string MainTitle { get; set; }
public string SubTitle { get; set; }
public int TotalSteps { get; set; }
public int CurrentStep { get; set; }
public int CurrentProgress
{
get
{
int ret = 0;
if (TotalSteps > 0)
{
double currentStep = CurrentStep;
double totalSteps = TotalSteps;
ret = Convert.ToInt32((currentStep / totalSteps) * totalSteps);
}
return ret;
}
}
#endregion
#region Define the Events
protected void OnOperationStart(EventArgs e)
{
if (OperationStart != null)
OperationStart(this, e);
}
protected void OnOperationProgress(EventArgs e)
{
if (OperationProgress != null)
OperationProgress(this, e);
}
protected void OnOperationEnd(EventArgs e)
{
if (OperationEnd != null)
OperationEnd(this, e);
}
#endregion
#region Declare the Events
public event EventHandler OperationStart;
public event EventHandler OperationProgress;
public event EventHandler OperationEnd;
#endregion
StartTheProgressBar.txt
This Text file has just a couple of lines of code that must replace the current call to the class using the StandAloneProgessBar. As you can see from below, I've actually captured the entire instance of the old call being commented out and replaced by the two new lines of code.
Note the final line of code: sp.ShowDialog();
. It is referring to the last line of code in StandAloneProgressBar.cs
. That is the line where you substitute in the actual call to your method that uses the StandAloneProgressBar. (See step 8 below)
private void button1_Click(object sender, EventArgs e)
{
StandAloneProgressBar sp = new StandAloneProgressBar();
sp.ShowDialog();
}
InitialValues.txt
These four variables are the values the our version of the ProgressBar need in order to work. Please change the variable TotalSteps
! I am somewhat embarrassed to admit that I failed to follow this instruction when testing the demo. Right after the initializations is the line that calls the Start Event
of the StandAloneProgressBar. I placed it there to eliminate the chance of missing a needed function call.
TotalSteps = 10;
CurrentStep = 0;
MainTitle = "Testing the ProgressBar";
SubTitle = "";
OnOperationStart(EventArgs.Empty);
Step by Step Instructions to Insert the StandAloneProgressBar into a Project
1) Copy all three StandAloneProgressBar
files and the three Text files to your current working directory.
2) Right-click on the project name in the Solution Explorer window and choose "Add Existing Item…"
Select all the files you Want to copy and hit Okay.
3) Edit the class you need our ProgressBar to work in.
Copy all the text contained in the textfile Property and Event Declarations.txt
into the beginning of the class you need our ProgressBar to work in.
4) Edit StandAloneProgressBar.cs
code.
Refactor the namespace to your current project's namespace.
Find and Replace: the name of the class that needs to use this ProgressBar, (on or near line 20).
Recommend refactoring the name of myDemo
to something more pertinent for your project.
5) Copy the contents of InitialValues.txt
to the beginning of the method that uses this ProgressBar.
This also, contains the call to initialize our ProgressBar.
Change the Public Property TotalSteps
to what your correct count is to be. NOTE: This should be a variable.
Change the Public Properties MainTitle
and SubTitle
to your desired text.
6) Add the three lines of code that update the progress of our ProgressBar to an appropriate place in the repeating process:
SubTitle = "(name you want displayed on the SubTitle, or not)";
CurrentStep++;
OnOperationProgress(EventArgs.Empty);
7) Add these two lines of code to the end of the method using our ProgressBar. This terminates it.
// Operation is completed, terminate the ProgressBar.
OnOperationEnd(EventArgs.Empty);
8) In StandAloneProgressBar.cs
, at the very end of the code (line 47) that starts with the Shown Event
of the Form, change the name of the called method from mydemo.GetRSSFeed()
to the method that uses it. In this case of the included demo, it is myDemo.GetRSSFeed()
.
9) Comment out the current call to the method using our ProgressBar and copy the contents of StartTheProgressBar.txt
under it. These two lines of code will replace the call.
10) You are ready to try it out.
Points of Interest
This was an interesting challenge in that I had to take Erik's sublime code, setup for use as an interface and work through it to deterrmine
its core essence. I learned a lot about this code by reverse engineering it. Also, just want to mention one more time that the demo program has really nice examples of Linq to XML code for extracting RSS Feed page data. It resides in the RSSFeed.cs
file.
History
Final draft submitted 11/11/12.