Solved

WinForms - Invoking events on one form from another form

Posted on 2009-05-14
13
544 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

 
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
 
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

738 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