Access variable in Shared Sub - vb.net

is there a way to access a variable in Form_Load from an event handler?
Please dont mind the code, this is just a representation of my question.
Public Class Form
Public Sub Form_Load()
Dim x as string
x = MyClass.MethodGetValue()
End Sub
Private Shared Sub OnChanged()
MyClass2.MethodGetValue(x)
End Sub
End Class

It's about the scope of the variable. In your situation you need a class variable. This allows it to be used anywhere inside of this class.
Public Class Form1
Private x As Object 'pick the datatype that matches your needs
Public Sub Form_Load()
x = MyClass.MethodGetValue()
End Sub
Private Sub OnChanged()
MyClass2.MethodGetValue(x)
End Sub
End Class

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

Multi-Threading (Calling Sub From WorkerThread)

Need to call a sub that is coded written inside the block of form1 form an external worker thread. This is what I have written:
In Form1:
Public Delegate Sub UpdateControlDelegate(ByVal C As Label, ByVal txt As String)
Private Sub UpdateControl(ByVal C As Label, ByVal txt As String)
If C.InvokeRequired Then
C.Invoke(New UpdateControlDelegate(AddressOf UpdateControl), New Object() {C, txt})
Else
C.Text = txt
End If
End Sub
Public Sub DoStuff()
'we do some stuff then when it comnes time update a certain control:
Call UpdateControl(MyLabel, "My Text For The Label)
End Sub
In The workerThread that is located in a class:
Public Class MyClass
Public Sub UpdateData
Call Form1.DoStuff
End Sub
End Class
Does this look correct? The most simplest terms on what I am trying to achieve:
WorkerThread to call a Sub that is located in Class Form1
and that sub contains code that updates a couple controls in Form1.
After doing a little more research. I have figured it out. The initial code I have written is correct. The only thing missing is a reference to the form I need to update.
Here is the COMPLETE solution when needing to run a SUB from the UI that is called from the Worker Thread:
Public Class MyClass
'working thread is being within the subs of this class
Public MyForm1111 As Form1 '<------ The variable in this class that will reference to the form1 that we need
Public Sub MySubThatIsOnAWorkerThread
MyForm1111.DoStuff '<==== must call MyForm1111.DoStuff and NOT Form1.DoStuff
End Sub
End Class
The Sub Located In Form1:
Public Class Form1
Public Delegate Sub UpdateControlDelegate(ByVal C As Label, ByVal txt As String) 'Required Delegate
Private Sub UpdateControl(ByVal C As Label, ByVal txt As String) 'Sub to update controls
If C.InvokeRequired Then
C.Invoke(New UpdateControlDelegate(AddressOf UpdateControl), New Object() {C, txt})
Else
C.Text = txt
End If
End Sub
Public Sub DoStuff() 'the sub we need to call from the worker thread
'do some calculations and code
Call UpdateControl(MyLabel, "Some Text For Label")
End Sub
Private Sub Form1_Load()
MyClass.MyForm1111 = Me <==== Set the reference here in your Form1_Load
End Sub
End Class

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

A case for interface?

I have a class that should do different things with a form.
Because these "things" are specific to the form, I store the reference to the form like this:
Friend Class clsEdit
Private m_Form As frmMain
And I pass it to the class like this:
Public Sub New(ByRef uForm As frmMain)
m_Form = uForm
End Sub
Now when my class should do these "things", I do it like this:
MyEditClass.DoThings()
Internally it looks like this:
Public Sub DoThis()
m_Form.SetHookPaused(True)
m_Form.StopCommonTimers()
End Sub
Protected Overrides Sub Finalize()
m_Form.DoSomethingThatOnlyThisFormCanDo()
End Sub
I would now like to be able to use clsEdit on a different form as well.
This other form also has the functions "DoThings" and "DoSomethingThatOnlyThisFormCanDo".
However, when I change the declaration of m_Form to this
Private m_Form As Form
... I can't do this anymore:
m_Form.DoThings()
... because "DoThings" is not a property / function of "Form".
And when I change it to this:
Private m_Form As frmOther
... I can't do that anymore:
Public Sub New(ByRef uForm As frmMain)
m_Form = uForm
End Sub
Can anybody tell me how I could do this?
Create your interface:
Public Interface IFormStuff
Sub SetHookPaused(value As Boolean)
Sub StopCommonTimers()
End Interface
Replace the form variable with the Interface variable in the class:
Public Class clsEdit
Private m_Form As IFormStuff
Public Sub New(f As IFormStuff)
m_Form = f
End Sub
Public Sub DoThis()
m_Form.SetHookPaused(True)
m_Form.StopCommonTimers()
End Sub
End Class
Implement the Interface in each form:
Public Class Form1
Implements IFormStuff
and each form needs to implement those interface stubs:
Public Sub SetHookPaused(value As Boolean) Implements IFormStuff.SetHookPaused
' do something
End Sub
Public Sub StopCommonTimers() Implements IFormStuff.StopCommonTimers
' do something
End Sub
then you need to create the class at the form level:
Private myEdit As clsEdit = Nothing
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
myEdit = New clsEdit(Me)
End Sub
That's the gist of it.

Hiding function on nested class

Public Class Class1
Private names As List(Of String)
Private _class2 As New Class2
Public Sub AddName(ByVal name As String)
names.Add(name)
_class2.Add()
End Sub
Public ReadOnly Property AddAge(ByVal name As String) As Class2
Get
_class2.index = names.IndexOf(name)
Return _class2
End Get
End Property
Public Sub Clear()
names.Clear()
_class2.Clear()
End Sub
Public Class Class2
Private _age As List(Of Integer)
Protected Friend index As Integer
Public Property Age() As Integer
Get
Return _age(index)
End Get
Set(ByVal value As Integer)
_age(index) = value
End Set
End Property
Public Sub Add()
_age.Add(0)
End Sub
Public Sub Clear()
_age.Clear()
End Sub
End Class
End Class
How can I hide ,Sub Clear and Sub Add on class2, so they'll only be visible on class1, like;
Public Sub Clear()
names.Clear()
_class2.Clear() '<<<<<<<
End Sub
I want they do not be visible on Sub Main(), like they are below.
Sub Main()
Dim person As New Class1
person.AddAge("kid").Clear() '<<<<<<
person.AddAge("kid").Add() '<<<<<<
End Sub
If I put Protected, I class1 cannot access it. If I put Protected Friend, Sub Main() can still access them. Thanks for your help and time.
Used -Hans Passant- comment.
"Trust in .NET follows assembly boundaries. If you get two classes in one assembly then there are two programmers that know how to find each other if there's a problem. The only way to get what you want is to put these classes in a separate class library project. Which then lets you use Friend. And whomever writes that Main method doesn't have to be friendly."