VB.NET Windows Forms Variables Passing - vb.net

I have got a windows form with a Combobox and two datepickers objects in it. I want upon user selection of the values to pass the variables values to another windows form.
All I've seen is how to do this with showDialog method on an instance of the class, however this doesn't work for me as the user has to select a user from Combobox and pick the date range and click on search button.
A quick straight forward help will be appreciated as my time is running close to the deadline.
Thanks.

you can do something like this
1- creation of public event, singleton approach
Public Class EventClass
Private Sub EventClass()
End Sub
Public Shared Sub Invoke(sender as object, value as object)
RaiseEvent OnValueChange(sender,value) ' be sure OnValueChange is not nothing first
End Sub
Public Shared Event OnValueChange(sender as object,value as object)
End Class
2- raising the event, in the form that containing the combobox and datepicker
Handle the event of the combo on selected index changed
inside the event of combo raise the event as
EventClass.Invoke(ComboBox1,ComboBox1.SelectedValue)
and in the case of DateTimePicker use
EventClass.Invoke(DateTimePicker1,DateTimePicker.Date)
3- in the form that you want to pass the values to
public sub EventClass_OnValueChange(sender as object, value as object) handles EventClass.OnValueChange
' do your code here but be sure that this form was created before the form that contains the invoke or it will not be fired
end sub
hope this will help you

Related

Access the values of a form from an EventHandler

I have a program, where a user fills out a form, then clicks a button that opens a new window on top of the form. That window waits on data from a Port and executes a DataReceived Event Handler.
I want this event to process the data (into a simple string) and then run a method from the main form window, that will compile the form data with the input data and send it further.
However, when executing the method from the Event Handler I cannot access the values of the form - it produces errors, as if all the form elements were completely blank.
It seems the event is running in a new thread, which cannot access the main instance of the form. Is there any way of running the event on the main thread? Or give it the access? I have tried to use global variables, but even they are blank when read from the event... I have been stuck on this for almost two weeks now and I am completely lost...
How can I access the values of form fields inside that event? What is the simplest way of doing this?
EDIT: I want to add more detail on the problem. I have tried following some advice online and tried to use Delegates. This is simplified version of what I have (still not working):
There are two classes: frmMain and frmPortReader.
On start, frmMain opens in a new window. It contains a combobox (cbInput) and button (btnSend). Upon clicking btnSend:
If frmPortReader.IsHandleCreated Then
frmPortReader.Close()
End If
frmPortReader.Show()
The frmPortReader does some things (irrelevant to this problem), but it's main function is to trigger an event when the port receives data.
AddHandler readerSerial.DataReceived, AddressOf DataReceivedHandler
Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
' Larger code that reads the actual input, processes it, and assigns it to the variable indata
frmMain.ExecuteEvent(indata)
End Sub
Then, in the frmMain class:
Delegate Sub MF(inputData As String)
Dim DisplayData As New MF(AddressOf TestDisplay)
Private Sub TestDisplay(indata As String)
MsgBox("Received data: " & indata & "Currently Selected Index: " & cbInput.SelectedIndex)
End Sub
Public Sub ExecuteEvent(inData As String)
MsgBox("Before Delegate: " & cbInput.selectedIndex)
Dim paramsArray(1) As Object
paramsArray(0) = inData
BeginInvoke(DisplayData, paramsArray)
End Sub
When executing, the ExecuteEvent method displays two MessageBoxes with the data it reads from the form (selected index of ComboBox). The first one, being read directly without a Delegate, produces -1, while the one inside Delegate produces error: "cannot call invoke or begininvoke on a control until the window handle is created"
I think Hursey nailed it. You're using the default instance of frmMain when that is not the form that is being displayed on your screen.
Change:
frmPortReader.Show()
To:
frmPortReader.Show(Me)
Now, in frmPortReader, you can get a reference to the instance of frmMain using the Owner property:
Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
' Larger code that reads the actual input, processes it, and assigns it to the variable indata
Dim main As frmMain = DirectCast(Me.Owner, frmMain)
main.ExecuteEvent(indata)
End Sub

vb.net a forms "new" routine is being called before I even invoke the form

I have a form called "partmanager". On it is a button to show another form "parteditor" to allow editing details of a part. Clicking that button will show the form and pass in a variable to the parteditors "new" routine.
My problem is that when the calling form (partmanager) starts, it immediately calls new routine in the parteditor form before it (partmanager) is even initialized so the parteditor form does not get the string that is supposed to be passed in. Later, when the calling form is visible and I click the button to show the parteditor form, new has already been prematurely called and so is not called again and the form does not get the string passed in.
I hope this makes sense!
I can implement a property in the parteditor form and pass in my variable that way prior to showing the form and that will work, thereby not even requiring a "new" routine in the parteditor forms code.
So my question is, is implementing the property the proper way to pass this variable to the form being called, or am I not properly coding my forms? (I also have an intermediary module called "commands" where I have been defining command procedures, in this case just showing a form.)
any pointers would be appreciated, thanks!
here is the code for the button in the calling form:
Private Sub EditButton_Click(sender As Object, e As EventArgs) Handles EditButton.Click
Commands.EditPart(_PartNumber) 'call the editpart command
Me.Close()
Me.Dispose()
End Sub
here is the code for the form being called:
Public Class PartEditForm
Private _partNumber As String = String.Empty
Public Sub New(partNumber As String)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_partNumber = partNumber
End Sub
Private Sub PartEditForm_Load(sender As Object, e As EventArgs) Handles Me.Load
Label1.Text = _partNumber
End Sub
End Class
and here is the code in my "commands" module for loading/showing the form:
Public PartEditForm As New PartEditForm(_partNumber)
Public Sub EditPart(partnumber As String)
If PartEditForm.IsDisposed Then
PartEditForm = New PartEditForm(partnumber)
End If
PartEditForm.Show()
End Sub
you can save the routine in a dim variable and get this on the other form and close the first form or hide but you need get in new var and contine where stop before.

VB grab text from selected form

I was wondering how you would grab some text from a textbox in a selected form. I have a MDI form which contains X number of child forms. Each child form has a textbox in it with some text. When I hit the save button how do I know which form is selected and how do I grab the text from that textbox.
Private Sub Forms_Clicked(sender As Object, e As EventArgs) Handles Forms.clicked
globalVar = sender
End Sub
I was thinking to make an event that just detects when ever a form is clicked and save it's form/form ID in a global variable. Any thoughts?
You have to determine the active child from first and from there, you can check which text box you want to read its content.
Like bodjo said, you have the [YourMDIForm].ActiveMDIChild property.
What is unclear, like Plutonix said is where is your Save "Button". Did you meant :
a Save MenuItem from a MenuStrip on your MDI Parent Form ?
or a Save Button inside an MDI Child Form (or either another Form that is not part of the MDI Parent/Child system)
The first case is pretty straightforward : Use the .ActiveMDIChild of your MDIParent Form.
The secund may need some valid way to point to an actual active child form (similar to the one you tried with your globalVar... there are better ways to do it.
By the way, when you get your targeted MDIChild through .ActiveMDIChild, you must access the textbox with a Public, Friend or Protected variable. Usually, controls in forms are private. So you may have to :
Public Class [YourMDIChildClassName]
' ...
' create a Public Property
Public ReadOnly Property ContentToSave() As String
Get
Return [YourTextBox].Text
End Get
End Property
' or make your textbox public in the Form design
Public [YourTextBox] As TextBox
' ... the one or the other, not both.
' ...
End Class
Another way to access the "active" MDIChild, assuming all of your MDIChild are instances of the same class is to create a static (shared) property in your Child class :
Public Class [YourMDIChildClassName]
' ...
Private Shared _CurrentMDIChild As [YourMDIChildClassName] = Nothing
Public Shared ReadOnly Property CurrentMDIChild() As [YourMDIChildClassName]
Get
Return _CurrentMDIChild
End Get
End Property
' ...
End Class
And using the same thing you tried, but using .Activated instead of .Clicked
Public Class [YourMDIChildClassName]
' ...
Private Sub MyChildForm_Activated() Handles Me.Activated
_CurrenMDIChild = Me
End Sub
' And that's ALL this method SHOULD contain.
' If you try to add other activation tricks, like activating another Form,
' or firing up a DialogBox (worst case),
' everything will go WRONG and your application will hang in an endless loop !!!
' Be carefull when using .Activated.
' ...
End Class
Then you could access the currently active MDIChild using the static Property :
[YourMDIChildClassName].CurrentMDIChild
' => Gives you directly a VALID instance of your MDI Child (or Nothing !)
' Then you can use in your MDI Parent :
If [YourMDIChildClassName].CurrentMDIChild IsNot Nothing Then
Dim TextToSave As String = [YourMDIChildClassName].CurrentMDIChild.ContentToSave
' ... save your text...
End If
HOWEVER, because you've created a static (shared) pointer to the last active MDIChild (sort of, I know it's not a pointer like in C) you must update this pointer whenever you close an MDIChild Form !
Public Class [YourMDIChildClassName]
' ...
Private Sub [YourMDIChildClassName]_FormClosing( _
sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If _CurrentMDIChild Is Me Then ' And "Me" is closing right now...
_CurrentMDIChild = Nothing
' We don't want memory leak or pointer to a Form that has been closed !
End If
End Sub
' ...
End Class
We are not supposed to create custom way of handling Child Form activation. MDIParent.ActiveMDIChild is there for that. However, once we want to access extended/custom/specific Properties of the Child Form that doesn't initially exists in System.Windows.Forms.Form, we need to cast the MDIParent.ActiveMDIChild to the real Form derived Type of our MDIChild. That's one other way to do it, but it's just me : I don't like castings much. Always set IDE to :
Option Explicit On
Option Strict On
Option Infer Off
Forms.Clicked ... does this event (Clicked) really exist ? I'm aware of .Click but not "Clicked". Anyway :
Public Class [YourMDIChildClassName]
' ...
Private Sub MyChildForm_Clicked() Handles Me.Click
' This part is executed when you click INSIDE the Form,
' at a location where there is NO Control.
' If you click on a control, like a Textbox, a Picturebox, a Panel, etc
' this block IS NOT EXECUTED as you've clicked on a control,
' not on the Form !
End Sub
' ...
End Class

How to check a checkbox of form 1 from another form in vb.net?

I have two forms, form 1 and form 2 (windows application). How can i access and check a checkbox in form 1 from form 2. Initially i tried calling the form name and then the control like form1.chkCanada.checked = true, it did not work. And then i added a property in form 1
Public Property abc As Boolean
Get
Return chkCanadianStmtInd.Checked
End Get
Set(value As Boolean)
chkCanadianStmtInd.Checked = value
End Set
End Property
and then in form 2
Dim frm As New frm1
frm.abc = True 'Checked
And it still doesnt work. Am i missing anything here?
Alternatively you can pass a handle of form1 to form2 constructor
Form1:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim _form2 As New Form2(Me)
_form2.Show()
End Sub
End Class
Form2:
Public Class Form2
Public Sub New(ByVal _form1 As Form1)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_form1.CheckBox1.Checked = True
End Sub
End Class
Consolidating comments here:
In order to access controls on a form that shows another form to the user you have two options, if no interaction is needed with the first form while the second form is active you can use showdialog and do all of your logic after the second form has closed, if you ned to maintain the ability to interact with the first form while the second is still open then you need to use custom events.
Showdialog:
The simpler of the two options is to switch your form.show() function calls to form.showdialog(). This effectively tells the first form that it should stop processing at the form.showdialog() line and wait for the child form to close before proceeding. Once the second form is closed the first form will pick up where it left off and that would be where any processing that relies on the values of the second form would take place.
Custom Events:
If you want to allow the user to interact with both the first and second forms at the same time then you will need to use custom events. In order to do this you will need three things. The custom event, a raiseevent call and an event handler.
So in your Form2 class you will need to declare the custom event. In this case since you are trying to check(or uncheck I assume) a box your custom event declaration will look like:
public event ChangeCheckedValue(byref state as boolean)
Now on your button click event you will need to raise the event to the handler on Form1:
RaiseEvent ChangeCheckedValue(booleanValue)
Now that those statements are in place you will need to changed your form2 object that is being shown by Form1. What I normally do is make Form2 a form wide variable on Form1 and declare it like:
private withevents frm as Form2
Once you have the frm variable in your Form1 class you can add a handler for the ChangeCheckedValue event:
protected sub HandleCheckChanged(byref bln as boolean) handles frm.ChangeCheckedValue
'Set the checked state of your checkbox.
End sub
Once you have all that set up you should see what you expect.

vb.net winforms how raise a custom event to a different control

I have a made a custom datagridview with custom column objects. One of the columns in an edit button column which has a text box and a button to the right of it. This is a user control. What I am having problems with is when the user presses the button on the control I want an event to be raised on the datagridview which contains this column. I am doing this in winforms and vb.net. If anyone knows how to raise an event from the user control column which has the button to the datagridview which contains the column then it would be greatly appreciated.
Thanks
In your custom control, simply declare an event that the control will raise:
Public Class MyUserControl
Public Event MyEvent as EventHandler
...
'Somewhere in you user control code, you want to raise the event
RaiseEvent MyEvent(Me, EventArgs.Empty) 'using empty args for demo purposes
End Class
Then, in your form, you simply declare an event handler as usual:
Private Sub MyUserControl_MyEvent(sender as Object, e as EventArgs) Handles MyUserControl.MyEvent
... 'Whatever you need to do in reaction to the event
End Sub
Hope this helps