gsdevEE
asked on
C# - Pass long acting function from child form to parent form and add bgworker and progress bar ?
I have a wizard application that creates/publishes data to SQL server and creates a file - it is very sloppy right now in doing so, and I would like to make it wore elegant by passing all the parameters and functiopns out of the child form where the work is currently being done to the parent form, and I would like to put the offending function in a bd worker and add a progress bar, showing text on what is going on - I have no idea how to do this, and I would think it would be pretty straightforward, but here are the questions I have (I know how to restructur the functions)
1 - How to Close a child form, but before disposing, pass the needed function info into a bg worker on the parent form,. so that the function may now be done there.
2. Tie the function into the bgworker, and add a status bar as the process runs
3. Show what functions are being completed at what time in the progress bar dialog
I will include the code from bith forms to show what I am talking about
PARENT FORM CALLS CHILD FORM, AND ON RETURNED DIALOG RESULT PROCESSES REMAINING INFORMATION
private void OpenApplicationWizard()
{
WizardSheet wizard = new WizardSheet(WebServiceUrl. AbsoluteUr i);
//Here is how the child form is called, perhaps just call Show ?
DialogResult result = wizard.ShowDialog();
//THis code gets called after child form closes
SelectedApplicant = wizard.WelcomePage.Selecte dApplicant Name;
if (result == DialogResult.Cancel) return;
MyDataSet.Merge(wizard.wiz ardDataSet as DataSet, true);
Update.UpdateSubmissionLab els(0, MyDataSet);
_dataManager.SaveApplicati onData();
LoadNewFile("");
}
CHILD FORM CODE THAT CLOSES WINDOW AND RETURN DIALOG RESULT
//CUSTOM EVENT THAT CLOSES FORM
private void CompletePage_WizardFinish( object sender, WizardPageEventArgs e)
{
try
{
//CODE THAT WILL BE PUT INTO BGWORKER
UpdateApplication();
UpdateApplicant();
UpdateAgency();
UpdateProcedure();
UpdateSubmission();
UpdateProducts();
//END
//CODE THAT RETURNS DIALOG RESULT
ParentForm.DialogResult = DialogResult.OK;
}
catch (Exception ex)
{
StandardMessageBox.ShowMes sageBox(th is, ex.Message);
}
}
1 - How to Close a child form, but before disposing, pass the needed function info into a bg worker on the parent form,. so that the function may now be done there.
2. Tie the function into the bgworker, and add a status bar as the process runs
3. Show what functions are being completed at what time in the progress bar dialog
I will include the code from bith forms to show what I am talking about
PARENT FORM CALLS CHILD FORM, AND ON RETURNED DIALOG RESULT PROCESSES REMAINING INFORMATION
private void OpenApplicationWizard()
{
WizardSheet wizard = new WizardSheet(WebServiceUrl.
//Here is how the child form is called, perhaps just call Show ?
DialogResult result = wizard.ShowDialog();
//THis code gets called after child form closes
SelectedApplicant = wizard.WelcomePage.Selecte
if (result == DialogResult.Cancel) return;
MyDataSet.Merge(wizard.wiz
Update.UpdateSubmissionLab
_dataManager.SaveApplicati
LoadNewFile("");
}
CHILD FORM CODE THAT CLOSES WINDOW AND RETURN DIALOG RESULT
//CUSTOM EVENT THAT CLOSES FORM
private void CompletePage_WizardFinish(
{
try
{
//CODE THAT WILL BE PUT INTO BGWORKER
UpdateApplication();
UpdateApplicant();
UpdateAgency();
UpdateProcedure();
UpdateSubmission();
UpdateProducts();
//END
//CODE THAT RETURNS DIALOG RESULT
ParentForm.DialogResult = DialogResult.OK;
}
catch (Exception ex)
{
StandardMessageBox.ShowMes
}
}
ASKER
Also - if you pass a Control collection out of a child form to the parent form, are those controls values still accessible when the child form closes ?
I would think that would be a no. If a child form is closed, all of it's controls get disposed of. I may be wrong though.
Your child form is being shown via ShowDialog():
DialogResult result = wizard.ShowDialog();
In "wizard" (child form), you are setting the DialogResult with:
ParentForm.DialogResult = DialogResult.OK;
That should really be:
this.DialogResult = DialogResult.OK;
This will cause "wizard" to automatically HIDE and code execution will return to the point where ShowDialog() was called.
At this point "wizard" is simply hidden and not disposed of. It is now that you should grab all the information you need from it and pass it to the BackgroundWorker.
The key here is that you do NOT need to pass anything from the child to the parent.
Instead, the parent will TAKE the information from the child after the ShowDialog() call.
*Remember that code STOPPED in the parent at ShowDialog() and when DialogResult is set in the child execution returns there.
To obtain the information from the child you'll either need to:
(1) Change the controls Modifiers() property to public so they can be accessed from the parent.
< or >
(2) Create public properties in the child and set them to the desired values BEFORE setting DialogResult().
Here is a super simplified example:
DialogResult result = wizard.ShowDialog();
In "wizard" (child form), you are setting the DialogResult with:
ParentForm.DialogResult = DialogResult.OK;
That should really be:
this.DialogResult = DialogResult.OK;
This will cause "wizard" to automatically HIDE and code execution will return to the point where ShowDialog() was called.
At this point "wizard" is simply hidden and not disposed of. It is now that you should grab all the information you need from it and pass it to the BackgroundWorker.
The key here is that you do NOT need to pass anything from the child to the parent.
Instead, the parent will TAKE the information from the child after the ShowDialog() call.
*Remember that code STOPPED in the parent at ShowDialog() and when DialogResult is set in the child execution returns there.
To obtain the information from the child you'll either need to:
(1) Change the controls Modifiers() property to public so they can be accessed from the parent.
< or >
(2) Create public properties in the child and set them to the desired values BEFORE setting DialogResult().
Here is a super simplified example:
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
if (f2.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.label1.Text = f2.EnteredValue;
}
}
}
public partial class Form2 : Form
{
private string _EnteredValue;
public string EnteredValue
{
get { return this._EnteredValue; }
}
private void button1_Click(object sender, EventArgs e)
{
this._EnteredValue = textBox1.Text;
this.DialogResult = System.Windows.Forms.DialogResult.OK;
}
}
ASKER
Idle Mind your suggestion is good, as well as is Death 529 To explain my code further, I have a Form (WizardSheet), which in turn is then inherited by user control WizardPage, which is in turn then inherited by all of the controls that comprise the wizard (WelcomePage Control, CompletePage control) - would your suggestion differ with this info , or is it the same, as far as calling this.DialogResult = DialogResult.OK; if different can you explain the best way to do this ?
Thank you for your help, I am learning more than I did in school!
Thank you for your help, I am learning more than I did in school!
Whatever object was displayed with ShowDialog() is the one that DialogResult() should be set against.
If your "dialog" form has UserControls within it and "ParentForm" is actually referring to the main dialog then your original could should be fine. You would need to do some extra work to access the information contained with the usercontrols. Again, though, the same concept can be applied by creating properties on the main form that expose the Usercontrols themselves of information within them.
From a design standpoint, it looks like you've passed in the main parent dialog into the usercontrol so you can close it from within the usercontrol. A more "loosely coupled" approach would make the usercontrol raise a custom "CloseDialog" event that the main dialog form subscribes to. This way the main dialog can set DialogResult itself and also gather all the information from the other usercontrols if necessary.
If your "dialog" form has UserControls within it and "ParentForm" is actually referring to the main dialog then your original could should be fine. You would need to do some extra work to access the information contained with the usercontrols. Again, though, the same concept can be applied by creating properties on the main form that expose the Usercontrols themselves of information within them.
From a design standpoint, it looks like you've passed in the main parent dialog into the usercontrol so you can close it from within the usercontrol. A more "loosely coupled" approach would make the usercontrol raise a custom "CloseDialog" event that the main dialog form subscribes to. This way the main dialog can set DialogResult itself and also gather all the information from the other usercontrols if necessary.
ASKER
Ok - last question to either of you, or anyone listening for that fact...can anyone show me (in code) how I would report the progress via text (on top of my progress bar ) what is actually happening in the program, i.e.
//CODE THAT WILL BE PUT INTO BGWORKER
someLabel.Text = "Updating Applicationt";
UpdateApplication();
someLabel.Text = "Updating Aplicant";
UpdateApplicant();
someLabel.Text ="Updating Agency";
UpdateAgency();
someLabel.Text = "Updating Procedure";
UpdateProcedure();
etc....
Is this how I would do it ?
//CODE THAT WILL BE PUT INTO BGWORKER
someLabel.Text = "Updating Applicationt";
UpdateApplication();
someLabel.Text = "Updating Aplicant";
UpdateApplicant();
someLabel.Text ="Updating Agency";
UpdateAgency();
someLabel.Text = "Updating Procedure";
UpdateProcedure();
etc....
Is this how I would do it ?
Are going to use the actual BackgroundWorker() control?
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
...or is this a "background" worker implemented with manual threads?
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
...or is this a "background" worker implemented with manual threads?
ASKER
no, I was gonna use background worker control
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
http://www.c-sharpcorner.com/UploadFile/dwkrueger/BackgroundWorkerSimplified02122008215220PM/BackgroundWorkerSimplified.aspx
This might be the best one:
http://www.switchonthecode.com/tutorials/csharp-tutorial-using-the-backgroundworker-class