在 My.settings 中保存带有附加信息的 ListBox [英] Saving ListBox with Additional information in My.settings

查看:29
本文介绍了在 My.settings 中保存带有附加信息的 ListBox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始在 VB.net 上学习列表框,并想创建一个包含附加信息的学生列表:

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

Private Class Students
    Private m_Name As String
    Private m_Age As String

    Public Sub New(ByVal new_Name As String, ByVal new_Age As String)
        m_Name = new_Name
        m_Age = new_Age
    End Sub

    Public Overrides Function ToString() As String
        Return m_Name
    End Function

    Public Function Age() As String
        Return m_Age
    End Function
End Class

因此,学生按如下方式添加到列表框中:

So, students add to the listbox as follows:

ListBox1.Items.Add(New Students(StudentName.Text, StudentAge.Text)) 
'StudentName and  StudentAge are textboxes.

但我也想保存这些信息,以便在程序重新启动时自动输入.我试着先做一个事件,保存 ListBox 中的每个项目,但使用上面的函数不起作用.

but I also wanted to save this information so that it is automatically entered when the program is restarted. I tried to do first an event that saves every item in the ListBox but using the function above it doesn't work.

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    For Each item In ListBox1.Items
        My.Settings.Students.Add(item)
        My.Settings.Save()
    Next
End Sub

然后我想加载这个信息,但就像关闭程序时保存信息的事件一样,它不起作用.

Then I would like to load this information, but just like the event with saving information when closing the program it does not work.

我收到一个 System.InvalidCastException The conversion of 'Students' to 'String' is not valid. 错误.

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    If My.Settings.Students Is Nothing Then
        My.Settings.Students = New Specialized.StringCollection
    Else
        For Each item In My.Settings.Students
            ListBox1.Items.Add(item)
        Next
    End If
End Sub

我想在加载后将这些信息显示在列表框中.

I would like to have these the information in listbox after load.

推荐答案

My.Settings 是一项功能,可让您管理应用程序的设置,例如;表单的最后位置和大小、控件的最后选择属性、最近打开的文件等.它不是 - 正如上面已经评论过的 - 一个存储和检索对象数据的地方.您的数据应该在数据库中或作为替代序列化.让我们试试序列化方法来解决您的问题.

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.

创建可序列化对象

  • Student 类:
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

  • Students 类:
  • <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
    

    您的新课程开始了!

    在包含 ListBox 的表单中,创建一个 BindingSource 类型,用于填充列表框、添加、编辑和删除 Student 对象.

    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
    

    在您的 Form 的构造函数或 Load 事件中,加载或创建一个 Students 类型的新对象,创建一个 BindingSource 的新实例,然后将其附加到 ListBox 的 DataSource 属性,如下所示:

    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
    

    其中 My.Settings.MyStudentsFile 是数据文件的路径.

    Where the My.Settings.MyStudentsFile is the path of the data file.

    列表框中将显示的是 ToString 为每个 Student 对象返回的内容.如果您只想显示 FullName,则设置列表框的 DisplayMember 属性如下:

    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"
    

    添加新的Student:

    Dim stu As New Student(
        "FirstName",
        "LastName",
        New DateTime(2000, 5, 22),
        Student.Genders.Male
    )
    bs.Add(stu)
    ListBox1.ClearSelected()
    ListBox1.SelectedItem = stu
    

    要修改 Student 条目的属性:

    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
    

    删除条目:

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

    要显示其他控件中的选定项,请按如下方式处理列表框的SelectedValueChanged事件:

    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
    

    最后,在 Form.FormClosing 事件中保存数据:

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

    仅此而已.

    这篇关于在 My.settings 中保存带有附加信息的 ListBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆