How to call a sub within anohter sub that is on a different form. VB.NET - vb.net

I'm self taught so pardon me if my terminoligy isn't correct.
I want to call a sub within another sub that is in a completely different form. but for some reason i can't get it to work. Maybe it's not possible. I'm not sure.
for a bit of background on the program. There's two pictureboxes. One has a binding source and the other does not. I want the one that doesnt have a binding source to display the same image as the other picture box once it has loaded.
so the first sub is in form2. code is as follows:
Public Sub GetImage()
Me.Pbox_Image.Image = Mainfrm.Pbox_Image.Image
Me.Pbox_Image.Refresh()
Me.Pbox_Image.Update()
End Sub
This procedure works fine when called within form2. But i want the code to run when mainfrm p_Imageload is completed.
The code I used in mainfrm is as follows:
Public Sub Patient_Image_LoadCompleted(sender As Object, e As AsyncCompletedEventArgs) Handles Patient_Image.LoadCompleted
GetImage()
End Sub
Visual studio displays an error and the code will not run. The error says that GetImage is not declared. I thought setting it to public would solve the issue but it didn't.
Any help is greatly appreciated.

You call it with adding a containing class infront of method, like this:
On FormX:
Sub
FormY.MethodZ()
End Sub

Related

Accessing text box on Form1 from Form2

I am new to vb.net so forgive me if this is an easy question.
I have a created a class library project that houses two windows forms, Form1 and Form2. The main class library has the event to open Form1. A button on Form1 launches Form2. The bulk of the code is in Form1, which I don't want to change if I can help it.
What I am trying to do, is access a sub that is on Form1 from Form2. That sub is changing the value of a text box on Form 1. I don't get any errors when I compile the project, however, nothing happens.
Here is an example
Form1:
Public Sub test()
Me.Panel1.Controls("Textbox1").Text = "Test"
End Sub
Form2:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim MainForm As New Form1
Me.Close()
MainForm.test()
End Sub
Don't get too caught up on how I built it out, I have tried about 20 different things and this is where I am at now.
I have tried defining Form1 in the sub test(). I have tried setting sub test() to shared. I have tried closing Form2 and activating Form1. I have tried changing the modifiers property on the text box to public. I have tried making Form1 the parent and Form2 a child (I honestly don't understand MDI very much). All these results end up in a project that will compile but wont give me any results. My code accesses the sub just fine, it wont access the text box's text property.
Any suggestions will help. I am trying to access the text boxes in a way that I can loop through all of them. For example: Me.Panel.Controls("Textbox" & i).Text = "Something". Also I would like to keep the sub in the class for Form1 if I can.
Any suggestions would be great!
You are creating a brand new Form1 in Form2, that is the problem.
Just use :
Call Form1.test()
By the way, I think this code in the sub is an easier way to set the text:
Panel1.TextBox1.Text = "Test"

Update control on main form via Background Worker with method in another class VB.Net

I have been banging my head against the wall all day trying to figure this one out.
I am finishing up a program to simply delete files in specific temp folders. I have read that it is sometimes good practice to create separate classes for methods and variables. So I have created a separate class for a couple methods to delete files and folders in a specified directory. I am using a Background Worker in my Form1 class and am calling my deleteFiles() method from my WebFixProcesses class in the DoWork event in the Form1 class. I am using a Background Worker so that I can easily report progress back to a progress bar on my main form.
The files get deleted without an issue but I just can't get the label on my main form to reflect the current file being deleted. the label doesn't change in any way.
I know the formula is correct as I can get this working if the method is in the Form1 class. and I simply use:
Invoke(Sub()
lblStatus.Text = File.ToString
lblStatus.Refresh()
End Sub)
here is my method that I am calling from the WebFixProcesses class:
Public Shared Sub deleteFiles(ByVal fileLocation As String)
For Each file As String In Directory.GetFiles(fileLocation)
Try
fileDisplay.Add(file)
For i = 1 To fileDisplay.Count
file = fileDisplay(i)
Form1.BackgroundWorker1.ReportProgress(CInt(i / fileDisplay.Count) * 100)
Next
IO.File.Delete(file)
Form1.labelText(file)
Form1.labelRefresh()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Next
End Sub
labelText() and labelRefresh() are methods from my main form which are using delegates to try to pass information to the control:
Public Sub labelText(ByVal file As String)
If lblStatus.InvokeRequired Then
Dim del As New txtBoxDelegate(AddressOf labelText)
Me.Invoke(del, file)
Else
lblStatus.Text = file.ToString()
End If
End Sub
Public Sub labelRefresh()
If lblStatus.InvokeRequired Then
Dim del As New txtBoxRefDelegate(AddressOf labelRefresh)
Me.Invoke(del)
Else
lblStatus.Refresh()
End If
End Sub
If anyone can help me out to inform me what I may be doing wrong it would be immensely appreciated as my head is in a lot of pain from this. And maybe I am going at it all wrong, and just being stubborn keeping my methods in their own class. But any help would be awesome. Thanks guys!
What Hans wrote on the question comment is true: Form1 is a type, not an instance, but to make things easier to newbye programmes (coming from VB6), M$ did a "mix", allowing you to use the form name as the instance of the form in the main thread.
This however works only if you are on that thread.
If you reference Form1 from another thread, a new instance of Form1 is created.
To solve the issue, add this code to the form:
Private Shared _instance As Form1
Public ReadOnly Property Instance As Form1
Get
Return _instance
End Get
End Property
We will use this property to store the current instance of the form. To do so, add this line to the Load event:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
_instance = Me
'other code here
End Sub
Now, from every class, in any thread, if you use
Form1.Instance
...you get the actual form. Now you can Invoke, even from the same form:
Me.instance.Invoke(Sub()
Me.lblStatus.Text = "Hello World"
End Sub)

Using button.enabled outside the Button_Click sub

I am just starting out with Visual basic .Net. I am designing an application where each button should disable itself after a registering a single click on it.
I am trying to add an additional sub, which when called, disables all of the buttons. (Disable_all())
Public Sub disable_all()
MsgBox("Testing disable_all")
Button_eight.Enabled = False
End Sub
One of the subs is calling it from the main module.
Private Sub disable()
Dim variab As Form1 = New Form1
variab.disable_all()
End Sub
The disable_all() sub however does not disable Button_eight when called. I placed a message box to check if the sub (disable_all) is getting executed, which it is. I get a message box having the text "Testing disable all" but the Button_eight is not disabled for some weird reason.
I'd really appreciate some help, thanks.
It's simple, just do Form1.disable_all().
That is, instead of variab.disable_all(), call: form1.disable_all() from the main module. Because as mentioned in the comments, new form1 creates a new instance of Form1.
You can also create a variable that point to the form dim var = form1 or dim variab as form = form1, but since you can access form1 directly from your module, it is unnecessary.

How can I get rid of this error? Visual Basic 2010

I have an array of pictureboxes, like this (they all have an image displayed on them, from the designer, from my.resources):
Dim imgSourcePic() As PictureBox = {imgAcronym, imgAcrostic, imgAdjective, imgAdverb, imgAlliteration, imgApostrophe, imgClause, imgComma, imgDialogue}
and another array of pictureboxes (which don't have an image displayed, yet):
Dim imgDefinitiontoMatch() As PictureBox = {imgDefinition1, imgDefinition2, imgDefinition3, imgDefinition4, imgDefinition5}
In the sub NewGame() I have a line of code which is:
imgDefinitiontoMatch(intX).Image = imgSourcePic(intRandomNumber).Image
But, whenever it executes this line of code I get this error:
I debugged it and saw that the pictureboxes, in the array, are displaying the Image property as 'Nothing'.
How else can I assign an image to the pictureboxes in imgSourcePic() that'll work?
I have tried creating variables for all of the images, such as:
Dim picAcronym As Image = My.Resources.Acronymn_definition
...
But still doesn't achieve anything.
I hope this isn't a duplicate, but I have been trying to figure it out all day and can't seem to make
it work :(
Many thanks and, as always, hope this makes sense.
You're populating those arrays before InitializeComponent() runs, so all of the variables are still Nothing.
You need to assign the array in Sub New(), after InitializeComponent() (which creates the actual PictureBoxes)
You can also use the Load() Event of the Form, which I see you already have in your code:
Public Class Form1
Private PBs() As PictureBox
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
PBs = {PictureBox1, PictureBox2, PictureBox3}
' ... more code ...
End Sub
End Class

Delegates not working in another module

Running into an odd issue with tasks and delegates. Code in question is running under dotNET 4.5.1, VS2013. On the form's code I have a sub that updates a grid, it checks to see if an invoke is required, and if it is it calls a delegate. When a task runs that's called in the same module, it works as expected, no problems. Threaded or not, the grid updates properly.
However, if the same thing is called from another module, the delegate never gets called and the visual component doesn't get updated. Just a watered down bit of pseudocode to clarify..
In the form's module:
Private Delegate Sub DoWhateverDelegate(ByVal _____)
Public Sub DoWhatever(ByVal _____)
If MyComponent.InvokeReqired
Dim Delegated As New DoWhateverDelegate(AddressOf DoWhatever)
Debug.Print("The delegate fired")
Invoke(Delegated, _____)
Else
' .. carry on as usual ..
End If
End Sub
Elsewhere....
Task.Run(Sub()
' .. various things I'd rather not block the UI thread with ..
DoWhatever()
End Sub)
Works fine. I can do Task.Run__ that calls DoWhatever and it's all happy and good. However if I create a task in another module and call DoWhatever, it doesn't fire the delegate and that visual component doesn't update. The code is identical, in the same module it works, in another module it does not.
I'm probably missing something blatantly obvious.. anyone care to point out my mistake? Thanks.
Edit -- just to clarify, that other module is just code, there's only one form in the entire solution. It's created at program startup automatically, there is no other form creation going on.
Should be a thread-specific issue. Check this:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
foo.DoSomething()
End Sub
End Class
The class with the delegate:
Public Class foo
Public Shared Sub DoSomething()
Task.Run(Sub() UpdateText())
End Sub
Public Delegate Sub UpdateTextDelegate()
Public Shared Sub UpdateText()
Dim f = Form1
'Dim f As Form1 = Application.OpenForms("Form1")
If f.InvokeRequired Then
Dim d As UpdateTextDelegate = AddressOf UpdateText
f.Invoke(d)
Else
f.TextBox1.Text = "Hi"
End If
End Sub
End Class
Run the code and the textbox will not be updated. Use the second f=.... (that one that take a reference from OpenForms) and it will be updated.
If you just try to access the default instance and you are outside the UI-thread, a new instance of the form will be created. That means, the content IS updated, but because that form is not shown, you will not see it.
NOTE I do NOT advise to solve your problem, by using OpenForms. I'd advise to correctly instantiate forms!
Add a new module/class to your code:
Module Startup
Public MyForm1 As Form1
Public Sub main()
MyForm1 = New Form1
Application.Run(MyForm1)
End Sub
End Module
Go to project properties -> application. Disable application framework and choose Sub Main as your start object. In the app, access your form via MyForm1 - or whatever you want to name it. Problem should be gone then.