Saving ListBox with Additional information in My.settings

前端 未结 1 496
囚心锁ツ
囚心锁ツ 2020-11-30 15:48

I recently started learning listboxes on VB.net and wanted to create something like a student list with additional information:

Private Class Students
    Pr         


        
相关标签:
1条回答
  • 2020-11-30 16:33

    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.

    0 讨论(0)
提交回复
热议问题