Solved

WinForms - Invoking events on one form from another form

Posted on 2009-05-14
13
540 Views
Last Modified: 2013-11-26
I have an app that opens a form that contains a CR Viewer control. I have added a button so that when you click the button on the (reportForm) it fires the click event in the mainform and starts a download for data.  This way I can refresh the data without closing and reopening the form.

The problem is that when I click the "refresh" button on the reportForm, it fires on the main form, is caught, but it seems to run through the code 2 times...like I clicked the main download button twice.  That really isn't possible since the main button is disabled as soon as it is clicked, but I know it runs 2 times because the thread that does the download, its thread_complete code runs 2 times causing me errors.

in the main form I have declared a ToolStripButton, since that is what is used on the reportForm, as the following:
Private WithEvents refreshDataButton as ToolStripButton

Then when the reportForm is created, I "link" the buttons...
dim viewer as new reportForm
refreshDataButton = viewer.reportRefreshButton
viewer.Show()

I then catch the click event of the refreshDataButton in the mainform, but the code that runs gets ran 2 times...I will post more code if needed...

Any help is appreciated...
0
Comment
Question by:rgn2121
  • 9
  • 4
13 Comments
 
LVL 12

Author Comment

by:rgn2121
ID: 24392514
Okay...I think I might know what it is, but I am not sure how to get around it.  When the download is finished, I raise an event in the main form RefreshDataCompleted.  to catch this event I declare an instance of my main form in the report form:
private tempMainForm as new mainform
This way I can handle the event tempMainForm.RefreshDataCompleted.  This is what causes me issues though, or so I guess, by me declaring and intializing the mainform in the reportform, when button clicks happen it happens in both, even though I can only visibly see one.  I see it hitt he thread_Completed in Debug, because it hits that event twice?
Not sure if this is confusing or makes since, but that is where I am at... I tested this by adding another declaration of main form to the report form and it hit my thread completed an extra time.  So it hits once for my main form and then once for each instance I have declared.
 
0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392524
Maybe this is because when I open my main Form I just do mainForm.show() instead of
dim myMain as New mainForm
myMain.show()
???
0
 
LVL 11

Accepted Solution

by:
Muhammad Ousama Ghazali earned 500 total points
ID: 24392530
I think the following line in your code
refreshDataButton = viewer.reportRefreshButton
does not necessarily move the button on Report Form into the Main Form. So if you have code written behind the Refresh button on Report Form, it is executed twice, once in response to the click on button on Report Form and second time in response to the event raised for button declared/created in Main Form. I might be wrong in suggesting all thing but this is one possibility.
The second point is I could not understand what you are trying to acheive? Please correct me if the following seems wrong to you:
  1. You need to download some data: on WinForms application which data are you trying to download? Do you mean to say download data into CR or what?
  2. If downloading does not mean to populate CR in Report Form and you need this download routine to be called from the Report Form, an easy way is to make a Public function of the Parent Form and call it from the CR form which will run the needed download code.
  3. If downloading just means to connect to a database and create dataset or other objects to populate CR and then display the Report Form itself, and you wish to avoid closing and opening this Report Form again and again just to refresh the report, then why not move this Refresh Routine into the Report Form itself. If there are certain parameters that you need to have within this routine that exist on Main Form, make either a Public function of Child Form to accept those values or create a Public Method and send those values to the object of Child Form.
If all above does not fit into your requirements, please post some more explanation and related code. Hope this helps.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392536
Nope...still hits it 2 times
0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392561
Thanks for the reply..
I have no code behind the viewer.reportRefreshButton.Click event other than
reportRefreshButton.Enabled=False
As to your questions...
1.  The mainForm loads and the user can click a button.  This button starts a download from Oracle Tables.  The data is downloaded, interpreted, and prepared for reporting.  When the user wants to view reports, then click a button that loads the reportForm.  Before the .Show() of this form I do the following.
dim viewer as New reportForm
viewer.RptData = TempDS
refreshReportViewerButton = viewer.refreshReportDataButton
viewer.Show()
This way the report Form has the DataSet and the ToolStripButton in the mainForm is linked to the ToolStripButton that users will click on the reportForm to refresh the data.
I am not sure I follow for 2 and 3...
0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392572
My download routine in the mainForm does a couple checks and then calls code from different DLL's to do the downloading and Interpreting.  If I was to call this from the report Form I would be duplicating a lot of code, unless I can call the method in the mainForm that starts the checking and downloading directly?
Not sure how to call a Sub in another form...
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 12

Author Comment

by:rgn2121
ID: 24392604
Okay...I was right about what was causing it...now I need to figure out how to fix it...  
I commented out the declarations of mainForm in my reportForm and everything ran as it should.  now I just need to know how to let the reportForm know that the new data is ready...
 
0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392646
I think I got what you were suggesting...maybe not, but I created a method in the reportForm and I call it from the mainForm when the refresh is completed.
This seems to work just as I expected the other to work without creating all the instance of my mainForm...  Is this what you were talking about or did I miss something along the way?

Friend Sub UpdateUIControls()

'code

End Sub

Open in new window

0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392746
One final point...I just read an article that said to create a Class that contains all of your forms as shared forms.  Once you have them all declared it tells you to setup your references when you actually create the form in code.
I pasted the samples below...I am curious what your thoughts on this is..?

Public Class myFormLibrary

    Public Shared Form1 As Form

    Public Shared myUserForm1 As Form

    Public Shared myUserForm2 As Form

End Class
 

Private Sub Form1_Load( _

	ByVal sender As System.Object, _

	ByVal e As System.EventArgs) _

	Handles MyBase.Load

    myFormLibrary.Form1 = Me

End Sub

Open in new window

0
 
LVL 11

Assisted Solution

by:Muhammad Ousama Ghazali
Muhammad Ousama Ghazali earned 500 total points
ID: 24392841
Take a new Module or Class in your project and create a method named DownloadData() which should return a DataSet after fetching records from the Oracle and processing them. In your main Form call this function and set the RptData to this returned DataSet and open the Report Form. Within your Report Form, do the same behind the click event of the Refresh button except to open the form.
Please have look the following code. There is no need to share the forms. Keep it simple and you'll have elegant applications those are easy to manage. The following solution also takes care of the duplicated-code fear of yours.

'GlobalRoutines.vb

Public Module GlobalRoutines
 

	Public Function GetReportData() As DataSet
 

		Dim dsTemp As DataSet

		

		'Return a dataset after connecting to oracle database, fetching records, and processing them

		Return dsTemp

		

	End Function
 

End Module
 

'MainForm.vb

'Create only one button to get/display report

'Write the following code behind click event of the button

Dim viewer As New ReportForm()

viewer.ReportData = GetReportData()

viewer.Show()
 

'ReportForm.vb

'Create a Refresh Data button and code the following in its click event

Me.ReportData = GetReportDate()

'Write code to refresh/reload the CRViewer object as necessary

Open in new window

0
 
LVL 11

Expert Comment

by:Muhammad Ousama Ghazali
ID: 24392846
You need to create a new Module in your project and may name it anything but the example above assumes it GlobalRoutines.vb. Further, mistakenly the name for the routine is wrongly written as DownloadData(), instead it should be GetReportData().
Hope it will help you.
0
 
LVL 12

Author Comment

by:rgn2121
ID: 24392932
I appreciate the code, but I have already created dll's that do all this for me on multiple threads.  All that works flawlessly and I can download and process 10's of thousands of records in seconds.  I do something very similar to what you suggest, but just by creating the reference between to buttons, I have gotten what I needed.
The mainform shows it's put clicked, the DataGridView refreshes it's data, the report form shows it's controls refresh and the data is available without the references to other forms.
I am curious what you think about the idea of a Forms Library though...I will award points for you code and suggestions.  Thank you...
0
 
LVL 11

Expert Comment

by:Muhammad Ousama Ghazali
ID: 24392996
It is always better to have Library for your code that you wish to share accross multiple projects and teams whether it be Forms, Controls, Components, DataAccess Routines, or simply some Code-based routines.
Maybe it is that I could not get the full imagination of what you wished to acheive, but it is good that you figured out something.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now