在 My.settings 中保存带有附加信息的 ListBox [英] Saving ListBox with Additional information in My.settings
问题描述
我最近开始在 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屋!