My.Settings is a feature that enables you to manage your application’s settings such as; the last location and size of a form, the last selected properties of controls, recently opened files, …etc. It’s not – as already commented above – a place to store and retrieve your objects’ data. Your data should be in a database or serialized as an alternative. Let’s try the serialization approach to solve your problem.
Create your Serializable objects
- The
Student
class:
Imports System.IO
Imports System.Xml.Serialization
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
<Serializable()>
Public Class Student
#Region "Enums"
<Serializable()>
Public Enum Genders
Unknown
Female
Male
End Enum
#End Region
#Region "Constructors"
Public Sub New() : End Sub
Public Sub New(firstName As String, lastName As String, dob As DateTime, gender As Genders)
Me.FirstName = firstName
Me.LastName = lastName
Me.DOB = dob
Me.Gender = gender
End Sub
#End Region
#Region "Public Properties"
Public Property FirstName As String
Public Property LastName As String
Public ReadOnly Property FullName As String
Get
Return $"{FirstName} {LastName}"
End Get
End Property
Public Property DOB As DateTime
Public ReadOnly Property Age As Integer
Get
If DOB = Nothing Then Return 0
Dim y As Integer = Today.Year - DOB.Year
If DOB > Today.AddYears(-y) Then y -= 1
Return y
End Get
End Property
Public Property Gender As Genders
#End Region
#Region "Public Methods"
Public Overrides Function ToString() As String
Return $"{FullName}, {Age}, {Gender}"
End Function
#End Region
End Class
- The
Students
class:
<Serializable()>
Public Class Students
#Region "Public Properties"
Public Property List As New List(Of Student)
#End Region
#Region "Public Functions"
Public Sub SaveXml(filePath As String)
Dim xs As New XmlSerializer(GetType(Students))
Try
Using fs As New FileStream(filePath, FileMode.Create)
xs.Serialize(fs, Me)
End Using
Catch ex As SerializationException
Console.WriteLine("Failed to serialize!")
End Try
End Sub
Public Shared Function LoadXml(filePath As String) As Students
Dim students As Students = Nothing
Dim xs As New XmlSerializer(GetType(Students))
Try
Using fs As New FileStream(filePath, FileMode.Open)
students = DirectCast(xs.Deserialize(fs), Students)
End Using
Catch ex As SerializationException
Console.WriteLine("Failed to deserialize!")
End Try
Return students
End Function
'Or if you prefer the binary format.
Public Sub SaveBytes(filePath As String)
Dim bf As New BinaryFormatter
Try
Using fs As New FileStream(filePath, FileMode.Create)
bf.Serialize(fs, Me)
End Using
Catch ex As SerializationException
Console.WriteLine("Failed to serialize!")
End Try
End Sub
Public Shared Function LoadBytes(filePath As String) As Students
Dim students As Students = Nothing
Dim bf As New BinaryFormatter
Try
Using fs As New FileStream(filePath, FileMode.Open)
students = DirectCast(bf.Deserialize(fs), Students)
End Using
Catch ex As SerializationException
Console.WriteLine("Failed to deserialize!")
End Try
Return students
End Function
#End Region
End Class
Your new classes in action!
In your form which contains the ListBox
, create a class level variable of BindingSource type which will be used to populate the list box, add, edit, and remove Student
objects.
Private bs As BindingSource
In your Form’s constructor or Load
event, load or create a new object of Students
type, create a new instance of the BindingSource
and attach it to the ListBox’s DataSource
property as follow:
If String.IsNullOrEmpty(My.Settings.MyStudentsFile) Then
'XML file.
My.Settings.MyStudentsFile = Path.Combine(My.Application.Info.DirectoryPath, "MyStudentsData.xml")
'or a binary file name if you prefer the binary formatter, for example.
'My.Settings.MyStudentsFile = Path.Combine(My.Application.Info.DirectoryPath, "MyStudentsData.dat")
End If
If File.Exists(My.Settings.MyStudentsFile) Then
obj = Students.LoadXml(My.Settings.MyStudentsFile)
'or
'obj = Students.LoadBytes(My.Settings.MyStudentsFile)
End If
If obj Is Nothing Then obj = New Students
bs = New BindingSource(obj, "List")
ListBox1.DataSource = bs
Where the My.Settings.MyStudentsFile
is the path of the data file.
What will be displayed in the list box is what the ToString
returns for each Student
object. If you’d like instead to display the FullName
only, then set the DisplayMember
property of the list box as follow:
ListBox1.DisplayMember = "FullName"
To add new Student
:
Dim stu As New Student(
"FirstName",
"LastName",
New DateTime(2000, 5, 22),
Student.Genders.Male
)
bs.Add(stu)
ListBox1.ClearSelected()
ListBox1.SelectedItem = stu
To modify the properties of a Student
entry:
If bs.Current IsNot Nothing Then
Dim stu As Student = DirectCast(bs.Current, Student)
stu.FirstName = "CorrectFirstName"
stu.LastName = "CorrectLastName"
stu.Gender = Student.Genders.Female
bs.ResetCurrentItem()
End If
To remove entries:
If bs.Current IsNot Nothing Then
bs.RemoveCurrent()
End If
'In case of multixxx SelectionMode
ListBox1.SelectedItems.OfType(Of Student).ToList.ForEach(Sub(stu) bs.Remove(stu))
To display a selected item in other controls, handle the SelectedValueChanged
event of the list box as follow:
Private Sub ListBox1_SelectedValueChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedValueChanged
If bs.Current IsNot Nothing Then
Dim stu As Student = DirectCast(bs.Current, Student)
TextBox1.Text = stu.FirstName
TextBox2.Text = stu.LastName
DateTimePicker1.Value = If(stu.DOB <> Nothing, stu.DOB, Now)
TextBox3.Text = stu.Age.ToString
End If
End Sub
Finally, to save your data in Form.FormClosing
event:
bs.EndEdit()
Dim stus As Students = DirectCast(bs.DataSource, Students)
stus.SaveXml(My.Settings.MyStudentsFile)
'or
'stus.SaveBytes(My.Settings.MyStudentsFile)
bs.Dispose()
That’s it all.