Calling functions outside class - vb.net

what is the correct way to call function outside the class, below code is also working
tried an alternate way by using delegate but couldn't figure out to pass function with parameters from Form class to classname so that form function can be called.
Public class form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
dim cl as new classname
cl.run()
end sub
function testmsg(txt as string)
msgbox(txt)
end function
end class
public class classname
public sub run()
txt = "xyz"
if(condition = true) then call form1.testmsg(byref txt as string)
end sub
end class

You can at any time, and in any place, and from a form, a class object, or even just standard vb module call/use a function (or in your case, it should be a sub).
Just mark any routine (sub/function) in the form as public.
eg:
Public function testmsg(txt as string)
msgbox(txt)
end function
NOw, in any other form, class or in fact any place you have code, you can thus go:
FormA.TestMsg("hi from form B")
so, there are no restrictions here. And any form wide scoped variables marked as public can also be used:
eg:
Public Class FormA
Public Zoo As String
Public Function TestMsg(txt As String)
MsgBox(txt)
End Function
Public Sub ShowZoo()
MsgBox("value of zoo = " & Zoo)
End Sub
End Class
So above is FormA
Now, any code from any ohter form, class or whatever can do this:
FormA.TestMsg("hi from form B")
FormA.Zoo = "this is zoo value"
FormA.ShowZoo()
So, just mark any variable as public (it in effect becomes a public property of that form).
And, just mark any function/Sub as pubic (it in effect becomes a public "method" of that form.

Related

Find out from within a class if an event handler exists in another class

A VB.NET 4 question.
Let's assume there exists a class A which contains an event E. In another Class (B), a variable of type A is declared WithEvents. At a certain point withing A's code, there will be a "RaiseEvent E" command. After that, is there a way to know if E was handled within B (just if a handler of event E exists in Class B)?
Obviously E could contain a parameter (i.e. boolean) so that if a handler within B handles it, it could set this parameter to True. This is not what i'm asking though. I would like to know if there is a built-in-to-.NET way to achieve this, without the use of any parameters.
A code example of what i'm trying to avoid (the use of parameter DoSomethingWasHandled):
Public Class A
Public Event DoSomething(ByRef DoSomethingWasHandled As Boolean)
Public Sub RaiseDoSomething()
Dim DoSomethingWasHandled As Boolean = False
RaiseEvent DoSomething(DoSomethingWasHandled)
End Sub
End Class
Public Class B
Public WithEvents SomeA As New A
Private Sub HandleDoSomething(ByRef DoSomethingWasHandled As Boolean) Handles SomeA.DoSomething
DoSomethingWasHandled = True
End Sub
End Class
A code example of what i'm asking if it exists:
Public Class A
Public Event DoSomething()
Public Sub RaiseDoSomething()
RaiseEvent DoSomething()
If DoSomething.WasHandled Then '<-- Does this check exist in any form? ***
DoSomethingElse()
End If
End Sub
End Class
Public Class B
Public WithEvents SomeA As New A
Private Sub HandleDoSomething() Handles SomeA.DoSomething
'DoStuff...
End Sub
End Class
*** This would just check if an event handler of E exists in class B and return True if it does, False if it doesn't.
Like this.
Public Class A
Public Event DoSomething(e As Object)
Public Sub RaiseDoSomething()
' adding 'Event' to the variable name of
' the event allows it to be checked
If DoSomethingEvent IsNot Nothing Then 'does the event have a subscriber(Event Handler)?
'yes
RaiseEvent DoSomething("TEST") 'because there is a handler this will be handled
End If
End Sub
End Class
Public Class B
Public WithEvents SomeA As New A
Private Sub HandleDoSomething(e As Object) Handles SomeA.DoSomething
Debug.WriteLine("Do")
End Sub
End Class
A test
Dim FOOa As New A
Dim fooB As New B
FOOa.RaiseDoSomething()
fooB.SomeA.RaiseDoSomething()

Access a base class property in inheritance class

I'm using the base class Button in VB.net (VS2017) to create a new class called CDeviceButton. The CDeviceButton then forms as a base for other classes such as CMotorButton, CValveButton.
I want to set the Tag property in the child class CMotorButton but access it in the constructor in CDeviceButton. Doesn't work for me. It turns up being empty.
The Tag is set in the standard property when inserting the CMotorButtom instance into a form.
I've also tried to ensure teh the parent classes' constructors are run by setting mybase.New() as the first action in each constructor but that didn't change anything.
Any ideas for improvements?
Public Class CDeviceButton
Inherits Button
Public MMIControl As String = "MMIC"
Public Sub New()
MMIControl = "MMIC" & Tag
End Sub
End class
Public Class CMotorButton
Inherits CDeviceButton
Sub New()
'Do Something
end Sub
End Class
When you try to concatenate Tag with a string, you are trying to add an object that is probably nothing. I set the Tag property first and used .ToString and it seems to work.
Public Class MyButton
Inherits Button
Public Property MyCustomTag As String
Public Sub New()
'Using an existing Property of Button
Tag = "My Message"
'Using a property you have added to the class
MyCustomTag = "Message from MyCustomTag property : " & Tag.ToString
End Sub
End Class
Public Class MyInheritedButton
Inherits MyButton
Public Sub New()
If CStr(Tag) = "My Message" Then
Debug.Print("Accessed Tag property from MyInheritedButton")
Debug.Print(MyCustomTag)
End If
End Sub
End Class
And then in the Form
Private Sub Test()
Dim aButton As New MyInheritedButton
MessageBox.Show(aButton.Tag.ToString)
MessageBox.Show(aButton.MyCustomTag)
End Sub
Below is my solution I came up with that works. Basically I make sure that all initialization has taken place before reading the Tag property. What I experienced is that the Tag property is empty until the New() in CMotorButton has completed, even though the Tag property has been set when creating the instance of CMotorButton in the Form. TimerInitate has a Tick Time of 500 ms.
Not the most professional solution but works for what I need at the moment.
Another option could be multi threading but that I haven't tried and leave that for future tryouts.
Public Class CDeviceButton
Inherits Button
Public MMIControl As String = "MMIC"
Public Sub New()
TimerInitiate = New Timer(Me)
End Sub
Private Sub TimerInitiate_Tick(sender As Object, e As EventArgs) Handles TimerInitiate.Tick
If Tag <> Nothing Then
TimerInitiate.Stop()
MMIControl = "MMIC" & Tag
End If
End Sub
End class
Public Class CMotorButton
Inherits CDeviceButton
Sub New()
'Do Some stuff
TimerInitiate.Start()
End Sub
Private Sub CMotorButton_Click(sender As Object, e As EventArgs) Handles Me.Click
End Class

How to hold a reference to a field in VB?

In VB, I have a class that does some standard validations. What I'd LIKE to do is to declare some variables, then create instances of a validator class that include pointers to the variables, and then at some later time execute the validators to test the values in the fields that are pointed to.
Something like this:
public class MyData
public property foo as string
public property bar as string
dim vfoo as validator
dim vbar as validator
public sub new()
vfoo=new validator(&foo) ' i.e. & operator like in C
vbar=new validator(&bar)
end sub
public sub validate()
vfoo.validate
vbar.validate
end sub
end class
public class validator
dim _field as string* ' i.e. * like in C
public sub new(field as string*)
_field=field
end sub
public sub validate
if string.isnullorempty(_field) then
throw SomeException
else if not SomeOtherTest(_field) then
throw SomeOtherException
end sub
The catch is that, to the best of my knowledge, there is nothing like C pointers in VB. Is there any reasonably easy way to do this?
At present I am passing in the field values at the time I call the validate() function, but this is not ideal because I would like to be able to create a List of validators specific to a given caller, and then loop through the List. But at the time I loop, how would I know which value from MyClass to pass in, unless I had a giant select statement keying off some "field code"? (And of course in real life, there are not just two fields like in this example, there are quite a few.)
Am I just having a brain freeze and there's an easy way to do this? Or can this not be done in VB because there are no such thing as pointers?
Like Java, VB doesn't make direct use of pointers (it compensates where it can with library/framework calls). In the context of a garbage-collected language, I can't imagine that this style of validation would work out well.
But for fun, maybe a lambda-based solution could suit?:
Public Class MyData
Public Property foo As String
Public Property bar As String
Dim vfoo As validator
Dim vbar As validator
Public Sub New()
vfoo = New validator(Function() foo)
vbar = New validator(Function() bar)
End Sub
Public Sub validate()
vfoo.validate()
vbar.validate()
End Sub
End Class
Public Class validator
ReadOnly _fieldFunc As Func(Of String)
Public Sub New(fieldFunc As Func(Of String))
_fieldFunc = fieldFunc
End Sub
Public Sub validate()
Dim _field = _fieldFunc()
If String.IsNullOrEmpty(_field) Then
Throw New Exception("NullOrEmpty")
ElseIf Not SomeOtherTest(_field) Then
Throw New Exception("SomeOtherTest")
End If
End Sub
Public Function SomeOtherTest(f As String) As Boolean
Return True
End Function
End Class

Calling private sub from module, concatenated reference

I have a couple of forms (i.e. frmTest) with bound comboboxes (i.e. cboTest). I'm trying to solve the NotInList event by a public sub, which calls back a button click sub's in these forms (i.e. btnTest_Click).
Form frmTest:
Private Sub cboTest_NotInList(NewData As String, Response As Integer)
Response = acDataErrContinue
Item_NotInList NewData, Me, "btnTest"
End Sub
Public Sub btnTest_Click
'....
End sub
Module:
Public strNotInList_Text As String
'public variable to store entered text
Public Sub Item_NotInList (strNewData As string, frmForm As Form, strControl As String)
Dim strControl_Sub As String
strNotInList_Text = strNewData
strControl_Sub = "." & strControl & "_Click"
Application.Run frmForm.Name & strControl_Sub
End Sub
Acces returns an error "Program ... didn't found a procedure frmTest.btnTest_Click."
Why ?
Reference frmTest.btnTest_Click looks to be correct. Sub btnTest_Click is declared as public.
Thank you for yor help.
Couldn't you create an interface let say IMyInterface with this method btnTest_Click (should be named differently) and let the forms you want to call this method implement this interface. Then change the signature of Item_NotInList like this:
Public Sub Item_NotInList (strNewData As string, frmForm As IMyInterface, strControl As String)
' ...
frmForm.btnTest_Click
' ...
Because the instance of the form is available in the method Item_NotInList you simply call the target method. Does this help?
Example:
Add class module and name it e.g. IMyInterface (can be named according to your needs). Add empty body of the method (don't add any implementation).
IMyInterface
Public Sub TestClick()
' will be implemented in your forms
End Sub
Then implement this interface in your forms e.g. in Form frmTest and others which should be used with the Item_NotInList method.
Form frmTest example
Implements IMyInterface
Private Sub IMyInterface_TestClick()
' here goes your implementation
End Sub
Standard Module test code
Sub test()
Dim f1 As UserForm1
Set f1 = New UserForm1
Item_NotInList f1
Dim f2 As UserForm2
Set f2 = New UserForm2
Item_NotInList f2
End Sub
Sub Item_NotInList(testForm As IMyInterface)
testForm.TestClick
End Sub
Thats it. HTH

VB.NET get type of derived generic list class from list item method

Public Class notifierMain
Public Class Contacts
Inherits List(Of row)
Public Sub New()
Dim r As New row()
Me.Add(r)
End Sub
Public Class row
Public Sub Validate()
Dim curType As String = Me.GetType().ToString
End Sub
End Class
End Class
Public Class MyContacts
Inherits contacts
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim c As MyContacts = New MyContacts()
c(0).Validate()
End Sub
End Class
When I debug this winforms application I get curType = "notifier.notifierMain+Contacts+row"
I want to the Validate function to know it is in MyContacts. How do I do this?
You're tostring()'ing gettype which returns a property called full name.
just check the .Name after get type and that'll have the result you want.
btw: this is a weird example, if you want validate() to return the name of the class you'll have to declare it as a function.
:)
The Me.GetType() is always going to return the type of the class it is enclosed in.
You will need to change Validate to a function and pass in the type of object being validated, but then you might as well call c(0).GetType() outside if the validation anyway!
See MSDN documentation for GetType
You can explore your generic type as shown in this MSDN article:
http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx
Hope this helps.