Form data erased after Windows form is closed - vb.net

I have a subsidiary form where I can enter data and then save it before closing the form and going back to using the main form.
When I re-open the subsidiary form, I cannot see the changes in the data that I had entered earlier.
Can anyone tell me where I'm wrong ?
MainForm.vb
Public Class Maincls
oTestObj as New Testcls
oTestObj.XYZ = "XYZ"
Private Sub SoftwareSettingsToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles SoftwareSettingsToolStripMenuItem.Click
Testcls.tbXYZ.Text = oTestObj.m_XYZ
Testcls.Show()
End Sub
End Class
Form_Testcls.vb
Public Class Testcls
Structure Params
Dim m_XYZ as String
End Structure
Dim oParams as Params
Public Sub New ()
InitializeComponent()
End Sub
Private Sub btnOK_Click(sender As System.Object, e As System.EventArgs) Handles btnOK.Click
XYZ = tbXYZ.Text
Me.Hide()
End Sub
Public Property XYZ() As String
Get
Return Me.oparams.m_XYZ
End Get
Set(ByVal value As String)
Me.oparams.m_XYZ = value
End Set
End Property
End Class

I think in windows forms the work around for this is to create a static class and add properties according to your requirement. Then populate these static properties on closing of your form. Now you can use the value set in the static data members, unless otherwise you change them on any other event.
Edit: In vb.net the Static is actually NonInheritable

Related

VB - Find child form from parent

I am in a project with multiple form.
I create a TicTacToe form here :
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
Dim page As Form = New TicTacToe
page.Show(Me)
End Sub
Here is a TicTacToe form:
Public Class TicTacToe
Public opponent as String
'Some code where user set opponent
Public Function Receive(S As String)
if string = opponent
'Some code
End Function
End Class
I would like to call my function Receive in my main form
If i do:
TicTactoe.Receive(S)
It call a instance of Receive where opponent does not exist.
I would like to find the oppened form of TicTacToe and call Receive
Thanks
Comments in line
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
page.Receive("Joe")
End Sub
'A form level variable to hold a reference to the instance of TicTacToe
'Although vb.net can use default instances, you have created an explicit
'instance of TicTacToe so you need to keep a reference if you want to
'refer to this instance.
Private page As TicTacToe
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
page = New TicTacToe()
page.Show(Me)
End Sub
Partial Public Class TicTacToe
Inherits Form
Public opponent As String
'Functions must be declared as a Type
'If you do not need a return value use a Sub
Public Function Receive(S As String) As String
Dim someString As String = ""
If S = opponent Then
'Do something
End If
'There must be a return Value
Return someString
End Function
End Class
Use this to show the form
Dim page As TicTacToe
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
page = New TicTacToe
page.Show(Me)
End Sub
Then you can use
page.Receive(S)
Edit
To use multiple forms
For Each f As TicTacToe in Application.OpenForms().OfType(Of TicTacToe)
f.Receive (S)
Next
In C#, you'd need a new instance, but as you are in VB, the compiler already does that for you.
What you are currently doing, is creating a new instance of the TicTacToe form and showing it:
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
Dim page As Form = New TicTacToe
page.Show(Me)
End Sub
But you don't save that instance anywhere. Then, in your next piece of code, you are using a different instance, which is the static one created by the compiler:
TicTacToe.Receive(S) // TicTacToe is the static instance
Therefore, you end up calling two different instances, which explains why there is no opponent set.
To get around this problem, do not create a new instance. In your Private Sub MenuTicTacToe, just use the instance created by the compiler, and you won't have this problem, just like this:
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
TicTacToe.Show(Me)
End Sub
Hope this helps.

Set the textbox value of usercontrol from Main winForm Button

I have a main Form 'frmMaster' that contains on one button 'btnSet',
inside this main form I put a panel control contains on usercontrol,
on this user control there is one textbox,
my question is how to set the value of this textbox when I click on the button 'btnset' from main form,
for example: when I click on 'btnset' from main form, the value of textbox on the usercontrol will be "Welcome"
In userControl I Put:
Public Property TextBoxTxt () As String
Get
Return txtText1.Text
End Get
Set(value As String)
txtText1.Text = value
End Set
End Property
On Main Form I Put inside button:
Dim uc As New ucControl1
uc.txtText1.Text= "Welcome!"
Your UserControl Must be like :
Public Class UserControl1
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Public Property TextBoxTxt() As String
Get
Return txtText1.Text
End Get
Set(value As String)
txtText1.Text = value
End Set
End Property
End Class
In you MainForm add a button "btnSet" and a Panel "Panel1" ,so your code inside MainForm must be like :
Public Class frmMaster
Private Sub btnSet_Click(sender As Object, e As EventArgs) Handles btnSet.Click
Dim uc As New UserControl1
uc.txtText1.Text = "Welcome!"
Panel1.Controls.Add(uc)
End Sub
Private Sub frmMaster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
End Class
I have create a simple exemple for you
In the user control:
Public Property TextBoxTxt () As String
Get
Return Me.textbox.Text
End Get
Set(value As String)
Me.txtebox.Text = value
End Set
End Property
In your even click of the button 'btnset' :
Private Sub btnset_Click(sender As Object, e As EventArgs) Handles btnset.Click
Dim uc As New MyUserControl
uc.TextBoxTxt ="Welcome!"
End Sub
You will need to add a public property to the usercontrol, e.g.
Public Property TextBoxMessage As String
Get
Return textbox.Text
End Get
Set(ByVal value As String)
textbox.Text = value
End Set
End Property
Then you can display a message from inside your frmMaster:
usercontrol.TextBoxMessage = "Welcome!"

change GroupControl visibility of opened usercontrol from the form vb.net

I have one 'UserControl' that opened inside form,
this usercontrol has a 'GroupControl'
how can I make this 'GroupControl' hidden or visible when user click on a button that beings on the form
using vb.net
In the user control:
Public Property GroupControlVisible() As Boolean
Get
Return Me.GroupControl1.Visible
End Get
Set(value As Boolean)
Me.GroupControl1.Visible = value
End Set
End Property
Try this :
In you UserControl add a procedure how set visibility to your GroupControl :
Public sub SetVisibility (V as boolean)
YourGroupControl.visible=v
End Sub
In your form
Public Class Form1
Dim uc As New MyUserControl
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Controls.Add(uc)
uc.Dock()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
uc.SetVisibility(False)
'NB :MyUserControl is name of your usercontrol
End Sub
End Class
To Simplify, you can use :
MyParentForm.UserControlName1.GroupControlName.Visible = False
or
CType(MyParentForm.Controls("UserControlName").Controls("GroupControlName"), _
GroupControl).Visible = False
But the best way is create a property which allows changing the Visible property of the GroupControl in UserControl Class like this :
Public Property GroupControlVisibility() As Boolean
Get
Return Me.GroupControlName.Visible
End Get
Set(value As Boolean)
Me.GroupControlName.Visible = value
End Set
End Property

Passing values of an object between forms in VB.NET

Here's my problem.
I'm making a project in VB.NET that (currently) exists out of 1 class (let's call it User.vb here) and 2 WinForms (frmDisplay & frmMain).
Let's say User.vb is currently looking like this:
Public Class User
Private mName As String
Public Sub New(ByVal name As String)
Me.Name = name
End Sub
Public Property Name As String
Get
Return mName
End Get
Set(value As String)
mName = value
End Set
End Property
End Class
Let's also say the form frmDisplay is just a form with a textfield txtString and a button btnSend.
Public Class frmDisplay
Dim usr As New User()
Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
usr.Name = txtString.Text
frmMain.Show()
Me.Hide()
End Sub
End Class
On the form frmMain I want to reach the value in the property Name that I stored in the class User on the first form.
The basic idea is (I know it doesn't work):
Public Class frmMain
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblStoredString.Text = usr.Name << This is where I'm stuck
End Sub
End Class
I googled my problem and read many posts, but I just can't seem to understand it. Maybe you guys can help me. I am new to VB.NET and WinForm-stuff (about 3 months of exp.), but I have done some programming in the past in C# with webapplications.
Every bit of help is greatly appreciated.
Thanks a lot in advance!
Will there only ever be one User.Name that you are interested in throughout the app?
If yes, then change the class to:
Public Class User
Public Shared Name As String
End Class
Then you can use User.Name from any form (or anywhere in the application) to get/set that value.
Note that you can still wrap the field in a property if you like:
Public Class User
Private Shared _Name As String
Public Shared Property Name As String
Get
Return _Name
End Get
Set(value As String)
If (value.Trim <> "") Then
_Name = value.Trim
End If
End Set
End Property
End Class
My focus is ASP.NET, and I prefer C#, but I'll chime in. There are numerous ways of providing data between the forms. The first one that comes to mind is to use a cache of some kind. The idea is that once the cache is made available to your program, you can add the value to the cache when the button is clicked, and then safely read the value whenever you need it. This can be a static class with a Dictionary, or you can look into using the functionality provided by the System.Web.Caching namespace. http://www.codeproject.com/Articles/8977/Using-Cache-in-Your-WinForms-Applications has an example.
Another way would be to use a shared data source. The concept is similar to the caching, but this would allow you to pass more complex relational data between your forms, assuming your real goal is more complicated than you describe. Here is a walkthrough for that: https://msdn.microsoft.com/en-us/library/ms171925.aspx.
You could be quick and dirty, and write the values to a text file at some location, and then read the values from the second form.
The simplest way is probably to define a custom constructor for the second form, and pass the values you need when you instantiate the second form. This is best suited if the values from the first form can be considered "parameters" to the instance of the second form. Passing a textbox value from one form to another in windows application
Declare the usr variable Friend
Public Class frmDisplay
Friend usr As New User()
It will then be available from the other form
Public Class frmMain
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lblStoredString.Text = frmDisplay.usr.Name
End Sub
End Class
It's a quirk of VB.NET that forms are automatically created with a public variable name the same as the class name. That's why you are able to use frmMain without having to create it (e.g. Dim frmMain as New frmMain). You can turn off this behaviour, but it isn't relevant to your problem.
On the other hand, if you want to do it "properly"...
Public Class frmDisplay
Private usr As User
Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
usr = New User(txtString.Text)
Dim f As New frmMain(Me, usr)
f.Show()
Me.Hide()
End Sub
End Class
and frmMain...
Public Class frmMain
Private myParent As Form
Private usr As User
Sub New(parent As Form, _usr As User)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
usr = _usr
myParent = parent
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Text = usr.Name
End Sub
Private Sub frmMain_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
myParent.Show()
End Sub
End Class
Here we instantiate frmMain and pass the User object to its constructor. We also pass the calling form so we can display it again when frmMain is closed.

Can't Remove Listview Item From Second Form

I am having an issue when trying to delete ListView Items from a second form.
For example, if I use the following command on Form1 it works:
Listview1.SelectedItems(0).Remove
However, if I attempt to remove from Form2 like so:
Form1.Listview1.SelectedItems(0).Remove
I get the following error:
"Invalid argument=value of '0' is not valid for 'index'. Parameter name: index"
I then tried to get a count of items from the listview on Form2 and it gives me a return of 0
Form1.Listview1.Items.Count
I'm not sure what my problem is.
Update
I have posted a brief example of my code (using your suggestion as I can understand it):
frmShowMessages
Private Sub ViewMessage()
Dim frm As New frmViewMailMessage
frm.Show()
End Sub
Public Sub DeleteItem(ByVal index As Integer)
lsvReceivedMessages.Items(index).Remove()
End Sub
frmViewMessage
Private instanceForm as frmShowMessages
Private Sub frmViewMailMessage_Load(sender As Object, e As EventArgs) Handles MyBase.Load
instanceForm = New frmShowMessages()
End Sub
Private Sub cmdDelete_Click(sender As Object, e As EventArgs) Handles cmdDelete.Click
instanceForm.DeleteItem(_index)
End Sub
Hopefully my code can help identify where my issue is.
In VB.net usually you get a default Form instance for each of your Form. Probably you are creating an instance of Form1 and then you are trying to access ListView1 of default instance.
E.g.
Sub ButtonClick()
Dim f As New Form1()
f.Show()
' at this point if you access f's ListView you will get correct count
f.ListView1.Items.Count
' however if you try to access default instance it will NOT have any item
Form1.ListView.Items.Count
End Sub
It means your instance f is NOT equal to default Form1 instance.
Solution can be, make the f variable as class level variable and use it everywhere. Or if Form1 will have only 1 instance, then you can use the default instance everywhere.
Personally I would NOT go with direct control accessing over forms. I would create a Public method which should return the data as list to the caller, in this case your Form2.
UPDATED-2:
As per your given scenario, I am simplifying things for you, and doing implementation using Event.
Public Class frmShowMessages
Private Sub btnOpenMessage_Click(sender As System.Object, e As System.EventArgs) Handles btnOpenMessage.Click
Dim frmView As New frmViewMessage(Me.ListView1.SelectedItems(0).Index)
AddHandler frmView.MessageDeleted, AddressOf DeleteMessageHandler
frmView.Show()
End Sub
Private Sub DeleteMessageHandler(sender As Object, e As frmViewMessage.MessageDeletedEventArgs)
Me.ListView1.Items.RemoveAt(e.MessageIndex)
End Sub
End Class
Public Class frmViewMessage
' a class which will be used for Event communication
Public Class MessageDeletedEventArgs
Inherits EventArgs
Public Property MessageIndex As Integer
Public Sub New(ByVal iIndex As Integer)
MyBase.New()
Me.MessageIndex = iIndex
End Sub
End Class
' main event which will alert the parent that a message deletion should be done
Public Event MessageDeleted As EventHandler(Of MessageDeletedEventArgs)
' private variable that will hold the MessageIndex
Private Property MessageIndex As Integer
' method that is responsible to raise event
Protected Overridable Sub OnMessageDeleted()
RaiseEvent MessageDeleted(Me, New MessageDeletedEventArgs(Me.MessageIndex))
End Sub
' we want to create this Form using the MessageIndex of ListView
Public Sub New(ByVal iMessageIndex As Integer)
Me.InitializeComponent()
Me.MessageIndex = iMessageIndex
End Sub
' the delete button will raise the event to indicate parent that
' a deletion of message should be done
Private Sub btnDelete_Click(sender As System.Object, e As System.EventArgs) Handles btnDelete.Click
Me.OnMessageDeleted()
End Sub
End Class