-
February 14th, 2011, 10:39 AM
#1
[RESOLVED] Updating Progress Bar on a separate form
I am attempting to update a progress bar on a separate form.
At the moment I have a massive bit of code which constantly changes how long it takes to complete depending on the options the user selects. The code takes place in a background worker on one form. The progress bar is named PBar and I currently have it set up in increments throughout the coding to update it. I have the call method which when the code meets a progress update it will complete the update to the progress bar but this does not happen as I cannot reference the bar on the separate form called Splash.
Please could you give me some steps/ code to complete this task,
Thanks
-
February 14th, 2011, 10:55 AM
#2
Re: Updating Progress Bar on a separate form
You could always create a public property in the splash form that allows you to set the value of the progress bar. Something like...
Code:
public partial class Splash : Form
{
public Splash()
{
InitializeComponent();
}
public int ProgressBarValue
{
get { return (this.progressBar.Value); }
set { this.progressBar.Value = value; }
}
}
Then just reference it from your main form.
Code:
splash.ProgressBarValue = 10; // or whatever the progress is between your ProgressBar's minimum and maximum values.
Last edited by RaleTheBlade; February 14th, 2011 at 10:58 AM.
R.I.P. 3.5" Floppy Drives
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein
-
February 14th, 2011, 11:11 AM
#3
Re: Updating Progress Bar on a separate form
I understand what you mean from there but on the main form it still doesn't recognise the calling of that process.
I'm not sure why it does that though.
-
February 14th, 2011, 12:55 PM
#4
Re: Updating Progress Bar on a separate form
How are you creating an instance of the Splash form? Do you have a reference to it from your main application form?
R.I.P. 3.5" Floppy Drives
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein
-
February 14th, 2011, 02:57 PM
#5
Re: Updating Progress Bar on a separate form
It is being referenced at the beginning of the background worker with
Code:
Form Splash = new Splash();
Splash.Show();
I've tried placing it in different positions as well but it doesn't seem to make a difference.
-
February 15th, 2011, 12:12 PM
#6
Re: Updating Progress Bar on a separate form
Ok, so you 're creating an instance of it on a BackgroundWorker object thread. Is there alot of code in your DoWork eventhandler? Can you post it so we can see what's going on? What might be happening is that you're creating this instance of Splash and showing it on a background thread and then the thread is ending, which would cause the form to be disposed of automatically.
R.I.P. 3.5" Floppy Drives
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein
-
February 15th, 2011, 02:26 PM
#7
Re: Updating Progress Bar on a separate form
Yes there is alot of code
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace Tourny_Manager
{
public partial class CreateDraws : Form
{
public CreateDraws()
{
InitializeComponent();
}
private void CreateDraws_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'tournyManagerDataSet.Tournament' table. You can move, or remove it, as needed.
this.tournamentTableAdapter.Fill(this.tournyManagerDataSet.Tournament);
// TODO: This line of code loads data into the 'tournyManagerDataSet.TournamentDetails' table. You can move, or remove it, as needed.
this.tournamentDetailsTableAdapter.Fill(this.tournyManagerDataSet.TournamentDetails);
this.tChoice.SelectedIndex = -1;
}
private void btnCreateDraws_Click(object sender, EventArgs e)
{
if (tChoice.Text != "")
{
if ((GU11.Text == "") || (BU11.Text == "") || (GU13.Text == "") || (BU13.Text == "") || (GU15.Text == "") || (BU15.Text == "") || (GU17.Text == "") || (BU17.Text == "") || (GU19.Text == "") || (BU19.Text == ""))
{
MessageBox.Show("Some Age groups have not been selected, Please confirm all of them, even if you do not require them.", "Age Group Selection", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
SaveFileDialog DialogSave = new SaveFileDialog();
DialogSave.DefaultExt = "xls";
DialogSave.Filter = "Excel File (*.xls)|*.xls|All files (*.*)|*.*";
DialogSave.AddExtension = true;
DialogSave.RestoreDirectory = true;
DialogSave.Title = "Where do you want to save the file?";
DialogSave.InitialDirectory = @"C:/";
if (DialogSave.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("You selected the file: " + DialogSave.FileName);
backgroundWorker1.RunWorkerAsync(new string[] { tChoice.Text, BU19.Text, GU19.Text, BU17.Text, GU17.Text, BU15.Text, GU15.Text, BU13.Text, GU13.Text, BU11.Text, GU11.Text, DialogSave.FileName });
}
else
{
MessageBox.Show("You hit cancel or closed the dialog. The draws will not be created");
}
}
}
else
{
MessageBox.Show("Please select a tournament.", "No Tournament Selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void lblDrawType_Click(object sender, EventArgs e)
{
}
private void tChoice_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable Comp = this.tournyManagerDataSet.Tournament;
DataRow[] RowTotal = Comp.Select("[Age Group] = 'BU19' AND [Tournament] = '" + tChoice.Text + "'");
int Entrants = RowTotal.Count();
lblNOGU11.Text = System.Convert.ToString(Entrants);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Form Splash = new Splash();
Splash.Show();
string[] Params = e.Argument as String[];
string tChoice = Params[0];
string BU19 = Params[1];
string GU19 = Params[2];
string BU17 = Params[3];
string GU17 = Params[4];
string BU15 = Params[5];
string GU15 = Params[6];
string BU13 = Params[7];
string GU13 = Params[8];
string BU11 = Params[9];
string GU11 = Params[10];
string FileName = Params[11];
Excel.Application oXL;
Excel.Workbook oWB;
Excel.Worksheet oSheet;
Excel.Range oRange;
// Start Excel and get Application object.
oXL = new Excel.Application();
// Set some properties
// oXL.Visible = true;
oXL.DisplayAlerts = false;
// Get a new workbook.
string location = @"C:\Documents and Settings\Nick\My Documents\Visual Studio 2008\Projects\Tourny Manager (Export Test)\Test.xls";
oWB = oXL.Workbooks.Open(location, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
backgroundWorker1.ReportProgress(1);
// Process the DataTable
// BE SURE TO CHANGE THIS LINE TO USE *YOUR* DATATABLE
DataTable dt = this.tournyManagerDataSet.Tournament;
try
{
dt.Columns.Remove("England Squash Number");
dt.Columns.Remove("Home Phone");
dt.Columns.Remove("Mobile Phone");
dt.Columns.Remove("Email");
dt.Columns.Remove("Email 2");
dt.Columns.Remove("T-Shirt Size");
dt.Columns.Remove("Position");
}
catch
{
}
DataRow[] Rows;
int rowCount;
backgroundWorker1.ReportProgress(2);
//BU19
Rows = dt.Select("[Age Group] = 'BU19' AND [Tournament] = '" + tChoice + "'", "Seeding");
if (BU19 == "8 Monrad")
{
// Get the active sheet
oSheet = (Excel.Worksheet)oWB.Sheets["8 M"];
oSheet.Copy(Type.Missing, oWB.Sheets["Winners"]);
oSheet = (Excel.Worksheet)oWB.Sheets["8 M (2)"];
oSheet.Name = "BU19";
rowCount = 1;
foreach (DataRow dr in Rows)
{
rowCount += 1;
for (int i = 1; i < dt.Columns.Count + 1; i++)
{
// Add the header the first time through
if (rowCount == 2)
{
oSheet.Cells[1, i + 115] = dt.Columns[i - 1].ColumnName;
}
oSheet.Cells[rowCount, i + 115] = dr[i - 1].ToString();
}
}
// Resize the columns
oRange = oSheet.get_Range(oSheet.Cells[1, 115],
oSheet.Cells[rowCount, dt.Columns.Count + 115]);
oRange.EntireColumn.AutoFit();
}
else if (BU19 == "16 Monrad")
{
// Get the active sheet
oSheet = (Excel.Worksheet)oWB.Sheets["16 M"];
oSheet.Copy(Type.Missing, oWB.Sheets["Winners"]);
oSheet = (Excel.Worksheet)oWB.Sheets["16 M (2)"];
oSheet.Name = "BU19";
rowCount = 1;
foreach (DataRow dr in Rows)
{
rowCount += 1;
for (int i = 1; i < dt.Columns.Count + 1; i++)
{
// Add the header the first time through
if (rowCount == 2)
{
oSheet.Cells[1, i + 115] = dt.Columns[i - 1].ColumnName;
}
oSheet.Cells[rowCount, i + 115] = dr[i - 1].ToString();
}
}
// Resize the columns
oRange = oSheet.get_Range(oSheet.Cells[1, 115],
oSheet.Cells[rowCount, dt.Columns.Count + 115]);
oRange.EntireColumn.AutoFit();
}
else if (BU19 == "32 Monrad")
{
// Get the active sheet
oSheet = (Excel.Worksheet)oWB.Sheets["32 M"];
oSheet.Copy(Type.Missing, oWB.Sheets["Winners"]);
oSheet = (Excel.Worksheet)oWB.Sheets["32 M (2)"];
oSheet.Name = "BU19";
rowCount = 1;
foreach (DataRow dr in Rows)
{
rowCount += 1;
for (int i = 1; i < dt.Columns.Count + 1; i++)
{
// Add the header the first time through
if (rowCount == 2)
{
oSheet.Cells[1, i + 115] = dt.Columns[i - 1].ColumnName;
}
oSheet.Cells[rowCount, i + 115] = dr[i - 1].ToString();
}
}
// Resize the columns
oRange = oSheet.get_Range(oSheet.Cells[1, 115],
oSheet.Cells[rowCount, dt.Columns.Count + 115]);
oRange.EntireColumn.AutoFit();
}
backgroundWorker1.ReportProgress(3);
//GU19
Rows = dt.Select("[Age Group] = 'GU19' AND [Tournament] = '" + tChoice + "'");
// Process repeated for GU19
backgroundWorker1.ReportProgress(4);
//GU19
Rows = dt.Select("[Age Group] = 'BU17' AND [Tournament] = '" + tChoice + "'");
// Process repeated for BU17
//etc. for GU17, BU15, GU15, BU13, GU13, BU11, GU11
backgroundWorker1.ReportProgress(12);
oWB.SaveAs(FileName, Excel.XlFileFormat.xlWorkbookNormal, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
backgroundWorker1.ReportProgress(13);
if (MessageBox.Show("Do you wish to view the created tournament now?", "View Tournament", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
oXL.Visible = true;
}
else
{
//Save the sheet and close
oSheet = null;
oRange = null;
oWB = null;
oWB.Close(Type.Missing, Type.Missing, Type.Missing);
oXL.Quit();
//Clean up
//NOTE: When in release mode, this does the trick
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
Splash.ProgressBarValue = e.ProgressPercentage;
// Set the text.
// Splash.lblLoading = e.ProgressPercentage.ToString();
}
}
}
That is everything on that form.
The problem is right at the bottom referencing the problem. I have also tried not including that and instead placing what you initially stated into the main section of code instead of the
Code:
backgroundWorker1.ReportProgress(10);
but that didn't seem to work either.
-
February 15th, 2011, 03:54 PM
#8
Re: Updating Progress Bar on a separate form
Well, your declaration and initialization of the variable Splash is local to the backgroundWorker1_DoWork eventhandler method. It can't be accessed by the backgroundWorker1_ProgressChanged eventhandler method since it's not in the correct scope. If you want to access the Splash variable, you need to declare it in the scope of the class.
Code:
private Form Splash;
public CreateDraws()
{
InitializeComponent();
}
// etc...
and initialize it and show it when the user clicks the btnCreateDraws button.
Code:
if (DialogSave.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("You selected the file: " + DialogSave.FileName);
this.Splash = new Splash();
this.Splash.Show();
backgroundWorker1.RunWorkerAsync(new string[] { tChoice.Text, BU19.Text, GU19.Text, BU17.Text, GU17.Text, BU15.Text, GU15.Text, BU13.Text, GU13.Text, BU11.Text, GU11.Text, DialogSave.FileName });
}
Then run your background worker and update it by handling the BackgroundWorker.ProgressChanged event as you're doing now. I usually prefix references to class variables with the keyword "this" so I can recognize the scope more quickly.
As for updating the progress bar on the Splash form, you will need to create a property in the Splash form code-behind itself that exposed the ProgressBar control. The easiest way would be to create a property like I had showed you earlier, then when you want to update the progress just call
Code:
this.Splash.ProgressBarValue = e.ProgressPercentage;
Alternatively, you could create and initialize it in the BackgroundWorker.DoWork eventhandler method like you are now and then pass it as the userState argument to the BackgroundWorker.ReportProgress() method. Then in the BackgroundWorker.ProgressChanged eventhandler method, cast e.UserState to Splash and update it that way.
Code:
Splash splash = (Splash)e.UserState;
splash.ProgressBarValue = e.ProgressPercentage;
Also, if your ProgressChanged event for your BackgroundWorker isn't being fired, check and make sure that the BackgroundWorker.ReportsProgress property is set to "true" in the forms designer window. Although an exception would be thrown if you called the BackgroundWorker.ReportProgress() method and the BackgroundWorker.ReportsProgress property was set to false.
Last edited by RaleTheBlade; February 15th, 2011 at 04:03 PM.
R.I.P. 3.5" Floppy Drives
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein
-
February 15th, 2011, 05:22 PM
#9
Re: Updating Progress Bar on a separate form
ok, that makes sense also however it still doesn't recognise the ProgressBarValue section in the splash form.
but when I include the line
Code:
Splash splash = (Splash)e.UserState;
It then recognises it but when the program runs it crashes with an error of
not code but easier to view:
Code:
System.Reflection.TargetInvocationException was unhandled
Message="Exception has been thrown by the target of an invocation."
Source="mscorlib"
StackTrace:
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Tourny_Manager.Program.Main()
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)
at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()
at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)
at System.Activator.CreateInstance(ActivationContext activationContext)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.NullReferenceException
Message="Object reference not set to an instance of an object."
Source="Tourny Manager"
StackTrace:
at Tourny_Manager.CreateDraws.backgroundWorker1_ProgressChanged(Object sender, ProgressChangedEventArgs e)
at System.ComponentModel.BackgroundWorker.OnProgressChanged(ProgressChangedEventArgs e)
at System.ComponentModel.BackgroundWorker.ProgressReporter(Object arg)
InnerException:
-
February 16th, 2011, 11:21 AM
#10
Re: Updating Progress Bar on a separate form
Did you create an instance of Splash in you DoWork eventhandler? And then did you pass that instance as an argument to the BackgroundWorker.ReportProgress() method? It should look something like this:
Code:
backgroundWorker1.ReportProgress(10, Splash);
I think the way I had told you before would work the best and make the most sense. Declare Splash as a class field, then initialize it and show it before you call the backgroundWorker1.RunWorkerAsync() method. Then, you don't have to pass it has an argument to the ReportProgress method. You can just reference it in your ProgressChanged eventhandler.
At the top of your class, add a field
Code:
private Splash splashForm;
public CreateDraws()
{
InitializeComponent();
}
...
and in your btnCreateDraws_Click eventhandler method, initialize the form and show it before you call backgroundWorker1.RunWorkerAsync()
Code:
...
if (DialogSave.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("You selected the file: " + DialogSave.FileName);
this.splashForm = new Splash();
this.splashForm.Show();
backgroundWorker1.RunWorkerAsync(new string[] { tChoice.Text, BU19.Text, GU19.Text, BU17.Text, GU17.Text, BU15.Text, GU15.Text, BU13.Text, GU13.Text, BU11.Text, GU11.Text, DialogSave.FileName });
}
...
then in your ProgressChanged eventhandler
Code:
this.splashForm.ProgressBarValue = e.ProgressPercentage;
And that should do the trick. It's a better design because it helps separate the UI functionality from the background data functionality.
R.I.P. 3.5" Floppy Drives
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein
-
February 16th, 2011, 06:21 PM
#11
Re: Updating Progress Bar on a separate form
Thank you so much!!! It now works!
I took what you just gave me and it needed the
Code:
private Splash splashForm;
which you just said instead of the previous
Code:
private Form Splash;
It now recognises it and works properly. Also using what you've given me I've managed to solve it to update the text on the splash screen as well.
Many thanks
-
February 16th, 2011, 10:48 PM
#12
Re: [RESOLVED] Updating Progress Bar on a separate form
You're welcome
R.I.P. 3.5" Floppy Drives
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." - Albert Einstein
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|