I do have Two Public Variables, each are from two different forms..
Form1.VB
Public UserNo As String
Form2.VB
Public MyUserNo As String
On my Form2.VB File, I assign value to the UserNo of Form1.VB
Form1.UserNo = MyUserNo
Whenever I access the Form1.VB, the Value of the MyUserNo got empty, What should I do? Both Forms are not closed.
I also tried to re-assign the value when I need to use it on the Form1.VB
UserNo = Form2.MyUserNo
First Correct is Syntax is:
Form1.VB
Public UserNo As String
Form2.VB
Public MyUserNo As String
In Form1
UserNo=Form2.MyUserNo
Second Thing:
First you should store some value in MyUserNo before storing it into UserNo.
That's why you are getting empty value.
Make the variable static/Shared and try again,it should work.
You can have more than one instance of a form, you know. Forms are objects, just like anything else. You need a variable in each form to hold a reference to the instance of each form that you are using.
If you don't call InitializeComponent(), your complete GUI is not going to render.
...
InitializeComponent()
Form1.UserNo = MyUserNo
...
Try this:
[Form1.UserNo = form2.MyUserNo]
it work
add it to form what you want value in next form
Function getvariable()
Return (VARIABLE)
End Function
In next form to get VARIABLE
VARIABLE2 = Form.getvariable()
Use variable value as Public
For Example
In Form1:
Public Str1 as String
So in Form2 you can use:
Str2=Form1.Str1
'In frmMain i Start frmBase
Dim f As New frmBase
f.Text = "New caption for frmBase"
f.ShowDialog(Me)
'in frmBase i read and write a textbox
Dim str As String = CType(Me.Owner, frmMain).txtRicetta.Text
Console.WriteLine(str)
CType(Me.Owner, frmMain).txtRicetta.Text = "12345"
Console.WriteLine(CType(Me.Owner, frmMain).txtRicetta.Text)
What you need to do is create your variables in a module as private, then generate some assessors for them.
Example:
Module modVariables
Private strUserNoSTR as String = New String(String.Empty)
Public Property getUserNoSTR() As String
Get
Return strUserNoSTR
End Get
Set(ByVal strUserNo As String)
strUserNoSTR = strUserNo
End Set
End Property
Private strMyUserNoSTR As String = New String(String.Empty)
Public Property getMyUserNoSTR As String
Get
Return strMyUserNoSTR
End Get
Set(ByVal strMyUserNo As String)
strMyUserNoSTR = strMyUserNo
End Set
End Property
End Module
After you generate the getter and setter public methods you can notice that your two private variables are within them, when you create the variables they are accessible from any form.
The reason why you keep losing the variables value is because when you try to access its value from another form (basically you're calling it from another class) the compiler has to create a new instance of that variable and when that happened the variable is set back to its original value which is of type empty string. Calling them from a module keeps them from being re-instantiated.
How To Use Them:
To get the value of strMyUserNo you call the getter of strMyUserNoSTR:
TextBox.Text = getMyUserNoSTR
To set the value of strMyUserNoSTR:
getMyUserNoSTR = someValuePlacedInThisVariable 'This sets it's value.
TextBox.Text = getMyUserNoSTR 'Now it's value is someValuePlacedInThisVariable.
Related
In the code below, when trying to remove an item from the Cases list the code breaks in the Setter with an index out of bounds. When running the debugger in VisualStudio 2017 it successfully goes through the Remove() function and deletes the last item but after returning to Main() it will break on the Setter and the call stack says it is coming from the Remove call. Example code below:
Sub Main()
Dim Cases As Collection = New Collection()
Dim caseIndex As Integer = 2
Cases.Remove(Cases(caseIndex))
End Sub
Public Class Collection
Public WithEvents Cases As List(Of CaseClass)
Public Sub New()
Cases = New List(Of CaseClass)()
Cases.Add(New CaseClass)
Cases.Add(New CaseClass)
Cases.Add(New CaseClass)
End Sub
Default Public Property BeltCase(ByVal Index As Integer) As CaseClass
Get
Return Cases(Index)
End Get
Set(ByVal Value As CaseClass)
Cases(Index) = Value
End Set
End Property
Public Sub Remove(ByRef BeltCase As CaseClass)
Cases.Remove(BeltCase)
End Sub
End Class
Public Class CaseClass
Public test As Int16
End Class
Call Stack:
TestingVBBug.exe!TestingVBBug.Module1.Collection.set_BeltCase(Integer Index,TestingVBBug.Module1.CaseClass Value) Line 25 Basic
TestingVBBug.exe!TestingVBBug.Module1.Main() Line 6 Basic
So why would we be going through the Setter at all. And why does that happen after we exit the remove function?
The problem is caused by your Remove() method, that is, you have a ByRef parameter (for some reason). When you use ByRef, any changes made to the parameter inside the method must be reflected to the variable that was passed to the method. That happens by reassigning the value to the original variable.
In your case, it works like this:
The Remove() method is called and a variable (Cases(caseIndex)) is passed to it.
Some work is done inside the Remove() method which might, or might not include changing the value of the parameter BeltCase.
The value of the parameter BeltCase gets reassigned to the variable that was originally passed to the method (which is Cases(caseIndex)).
As a result of the above step, the setter of the BeltCase property gets called with Index = 2 which raises the out of range exception because Cases(2) doesn't exist (was removed).
To confirm, you can see this problem go away when you replace this line:
Cases.Remove(Cases(caseIndex))
..with:
Dim myCase As CaseClass = Cases(caseIndex)
Cases.Remove(myCase)
That way, you create a new variable which refers to the same CaseClass object and most importantly avoid calling the setter of your Collection.BeltClase property.
However, a better solution would be to not use ByRef in the first place since you don't seem to need it in this situation. So, simply use Public Sub Remove(ByVal BeltCase As CaseClass) instead.
Check this question for more about ByVal and ByRef with objects.
One last thing, please don't call your class Collection because it can be very confusing to anyone looking at your project.
I can't find anything on this anywhere so here's my problem (although it is mostly a cosmetic one):
I have a class being used as a custom data type, but when I look in the locals or watch window I see that each Property Let has created an extra variable, which clutters the window with redundant variables and information (and potentially takes up extra space).
Example:
In class module Class1:
Private data As Integer
Property Get X() As Integer
X = data
End Property
Property Let X(ByVal Value As Integer)
data = Value
End Property
And to test:
Sub Test1()
Dim TestClass As Class1
Set TestClass = New Class1
TestClass.X = 100
End Sub
In the locals window:
Am I supposed to be recycling this extra variable somehow or am I doing something else wrong?
--- If you look at stock Excel objects (like a Worksheet) there are no duplicate variables whatsoever.
Edit: To clarify, I want to know if there is a way to hide the Property in the locals/watch window to make them easier to navigate.
It's fine. data is your private variable and X is just property. Nothing wrong about that. But you should consider naming convention, setters and getters for private variable should be somehow consistent, for example:
'Member variable, pName - private Name
Private pName As String
'Properties
Property Get Name() As String
Name = pName
End Property
Property Let Name(val As String)
pName = val
End Property
I have a listbox and a class.
The class is called CTS_Warnings_List
And the listbox is called lbpropWarningFacList
Here is the class:
Public Class CTS_Warnings_List
Public _Warning As String
Public _WarnID As Integer
Public Property Warning() As String
Get
Return _Warning
End Get
Set(ByVal value As String)
_Warning = value
End Set
End Property
Public Property WarnID() As Integer
Get
Return _WarnID
End Get
Set(ByVal value As Integer)
_WarnID = value
End Set
End Property
Sub New(ByVal Warning As String, ByVal WarnID As Integer)
Me.Warning = Warning
Me.WarnID = WarnID
End Sub
End Class
So now I want to add a new item to the listbox. So I tried this:
Dim llist As New CTS_Warnings_List("K", 8)
lbpropWarningFacList.Items.Add(llist)
I also tried this:
lbpropWarningFacList.Items.Add(New CTS_Warnings_List("K", 8))
When I run the app and add these to the listbox, in each case I get this displayed in the listbox:
NameOfApplication.NameOfClass
as the display in the listbox.
What am I doing wrong?
Thank you
Listboxes only knows how to display strings.
Therefor, when you add an item of any type to the listbox, it displays the value it gets by calling the items ToString() method.
You should override the ToString() method or simply enter items as strings in the first place.
In your case, add this to your class:
Public overrides function ToString() as string
return Me.Warning & " " & Me.WarnID.ToString()
End Function
You are sending a CTS_Warnings_List object to a listbox. How does the listbox know what to do with that object? It doesn't know what to do with that object. If you want to send the properties of the object to the listbox, then you have to do something like:
lbpropWarningFacList.Items.Add(llist._WarnID & ": " & llist.Warning)
Thanks for the responses. But I found that if I add
NameOfListBox.DisplayMemeber = "PropertyOfClass"
NameOfListBox.ValueMember = "PropertyOfClass"
By just adding this it now shows the correct data in the listbox.
Been working a lot with custom classes lately and I love the power you can have with them but I have come across something that I'm not able to solve and/or find anything helpful online.
I have a list of a class with properties I'm looking to only store information pulled from a database into.
Public Class CustomClass
Public _Values As String
Public _Variables As String
Public ReadOnly Property Values() As String
Get
Return _Values
End Get
End Property
Public ReadOnly Property Variables() As String
Get
Return _Variables
End Get
End Property
Sub New(ByVal values As String, ByVal variables As String)
_Values = values
_Variables = variables
End Sub
End Class
I will be iterating through some database entries, and I'm looking to store them into the appropriate property when I hit them (since I won't have them all available immediately, which is part of my problem). I want to just be able to add either the value or the variable at a time and not both of them, but since I have the sub procedure 'New' passing two arguments, it will always require passing them both. I've found the only way around this is by making them optional fields which I don't feel is the right way to solve this. Is what I'm looking to do possible with a class or would it be simpler by using a structure?
You can overload the constructor:
Friend Class Foo
' using auto-implement props:
Public Property Name As String ' creates a _Name backing field
Public Property Value as Integer
Public Sub New(newN as String, newV as Integer)
' access "hidden" backing fields if you want:
_Name = newN
_Value = newV
End Sub
Public Sub New() ' simple ctor
End Sub
Public Sub New(justName As String)
' via the prop
Name = justName
End Sub
End Class
You now have 3 ways to create the object: with full initialization, partial (name only) or as a blank object. You will often need a "simple constructor" - one with no params - for other purposes: serializers, Collection editors and the like will have no idea how to use the parameterized constructors and will require a simple one.
If rules in the App were that there was no reason for a MyFoo to ever exist unless both Name and Value being defined, implementing only the New(String, Integer) ctor enforces that rule. That is, it is first about the app rules, then about coding convenience.
Dim myFoo As New Foo ' empty one
myFoo.Name = "ziggy" ' we only know part of it
Since the default of string is nothing, you could pass nothing for the value you don't have. IE
Collection.Add(New CustomClass("My Value",Nothing))
Every type has a default, so this works with more than just strings.
I am trying to assign a value to global variable, which has a Property of type Double. This Property is passed as Object and the assignment fails.
In the example code below, the value is never assigned to the actual object, but only locally:
Public Class Form1
Friend Home As New Building
Private Sub AssignValues() Handles Me.Load
'Objects of different types are added to a list
Dim listObjects As New List(Of Object)
listObjects.Add(Home.Surface)
'All the Objects in listObjects are assigned a value that
'is stored as String
For Each o As Object In listObjects
SetProperty(o, "45.6")
Debug.Print("Surface = " & Home.Surface.ToString)
Next
End Sub
Private Sub SetProperty(ByRef Variable As Object, ByVal Value As String)
Select Case Variable.GetType
Case GetType(Double)
Variable = CDbl(Value)
Case Else
'...
End Select
End Sub
End Class
Public Class Building
Dim _surface As Double = 0
Public Property Surface As Double
Get
Return _surface
End Get
Set(ByVal value As Double)
_surface = value
End Set
End Property
End Class
The program invariably outputs Surface = 0 instead of 45.6. What am I doing wrong?
I tried to pass the Variable as reference, as suggested here, but without success. I also read about using Reflection, but there ought to be something simpler than that...
When your adding home.surface to the list, your adding a copy of the double to the list and then adjusting that copy. Stick a watch on "o" and see how it changes whilst home.surface remains the same.
If you want to use reflection, try something along these lines.
Dim prop As Reflection.PropertyInfo = o.GetType().GetProperty("Surface")
prop.SetValue(o, 45.6)
With Variable.GetType you will get always Object, because this is the type of Variable. What you can do with an Object is converting/casting it into a different type (like Double).
The best way to determine the "original type" from where the Object comes would be including an additional variable telling it. Another option might be converting the given Object into the target Type and see if it is not nothing/does not trigger an error. But this second option is not too accurate, mainly when dealing with "equivalent types" like Doubles/Integers.