我设置了这个空属性:
但是在将新的 ArrayList 对象分配给该属性后,该属性在每次应用程序执行中始终为空。
在 MyBase.Load 事件的处理程序中,我调用此方法,只是为了测试此问题:
sub blahblah handles mybase.load
me.CheckRecentFiles
end sub
Private Sub CheckRecentFiles()
Try
' This throws an object not referenced exception 'cause always is empty.
MsgBox(My.Settings.RecentFiles.Count)
Catch ex As Exception
MsgBox(ex.Message)
End Try
' Just for testing, if the collection is empty then I instance a new ArrayList
' and I assign it to the property and I save it and exit from the application.
' But even doing this the property is always empty in the next execution.
If My.Settings.RecentFiles Is Nothing Then
My.Settings.RecentFiles = New ArrayList
My.Settings.RecentFiles.Add({"test-Item1", "test-Item2", "Test-Item3"})
My.Settings.Save()
Application.Exit()
End If
End Sub
正如您在上面的代码中看到的,我分配了一个带有一个条目的新 ArrayList,但更改仅在应用程序执行期间生效,如果我退出应用程序,则该属性将再次变为空。
当然我也检查了这个选项:
但无论如何这是不必要的,因为我在代码中手动保存设置,所以......
为什么会发生这种情况?
我该如何解决这个问题?
UPDATE:
我已经调查过,似乎这是一个已知问题,数组、ArrayList 和任何通用集合(类型)都无法由 my.settings 保存(但另一方面,StringCollection 可以)
但是在this post的最后一个回答中(MemoryStream 答案)解释了一种简单的方法,可以将 ArrayList 的更改永久保存到 my.settings,然后在下一次应用程序运行时读取它。
答案似乎非常好,但我对代码和继续步骤有点迷失,所以有人可以解释那里解释的步骤,但请用人类可读的语言来解释?
我已经验证 ArrayList 保留在下一个应用程序运行中,是的,但我不确定我在做什么,因为如果 MemoryStream 包含旧的 ArrayList 那么我现在正在做的就是分配 My .Settings.MRU 设置为包含更多 Arraylists 的 Arraylist,而不是包含 String() 的原始 ArrayList?以及无论如何如何在保存设置后加载数组条目这边走?.
这是我从该答案中尝试过的:
' Create the ArrayList
Dim tmpArrayList = New System.Collections.ArrayList
tmpArrayList.Add({"test-Item1-1", "test-Item1-2", "Test-Item1-3"})
tmpArrayList.Add({"test-Item2-1", "test-Item2-2", "Test-Item2-3"})
' Serialize the arraylist entries:
Dim formatter As Runtime.Serialization.IFormatter =
New Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim ms1 As New IO.MemoryStream
formatter.Serialize(ms1, tmpArrayList)
' Save the ArrayList
My.Settings.MRU = New ArrayList(ms1.ToArray) ' I think it hould be like that?
' Load the ArrayList contained in My.Settings.MRU (no idea)
最佳答案
如果您的数据位于 arrayList(或 List 或 Collection)中,并且您正在查看 BinaryFormatter 来寻求解决方法,则没有充分的理由也使用 My.Settings。您可以通过 BinaryFormatter 执行它的操作,这只是保存文件并选择一个名称。
Imports System.Runtime.Serialization.Formatters.Binary
Private MRUArrayList = New ArrayList
' file location
myFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment. _
SpecialFolder.ApplicationData),
CompName,
ProgramName,
File)
保存设置:
Dim bf As New BinaryFormatter
Using fs As New FileStream(myFile, FileMode.OpenOrCreate)
bf.Serialize(fs, MRUArrayList )
End Using
加载设置:
' dont attempt for the first time run
If File.Exists(myFile) = False Then Return False
Dim bf As New BinaryFormatter
Using fs As New FileStream(myFile, FileMode.Open)
MRUArrayList = CType(bf.Deserialize(fs), ArrayList)
End Using
一旦你不得不求助于 BF 来解决问题,用文件流替换内存流就可以完全摆脱对 My.Settings 的需要,让你可以将文件存储在任何你想要的地方,并且它不会因版本、用户更改而改变EXE 名称或其他任何名称,除非您更改上面的文件名公式。
对于不仅仅是 MRU ArrayList 的应用程序,您可以在其位置使用类将所有设置存储到您想要的位置,就像设置一样。您只需将该类标记为 <Serializable>
。仍然需要一行代码来保存整个类,一行代码来重构它。虽然存在一些限制,但克服它们并不困难。
Private myNewSettings As New myNewSettingsClass
...
bf.Serialize(fs, myNewSettings)
myNewSettings = CType(bf.Deserialize(fs), myNewSettingsClass )
在其他情况下,您可以根据具体情况使用 XML 序列化程序或 ProtoBuf-NET。
您还可以在程序退出时自动保存新设置:转至项目属性 --> 应用程序 --> 单击查看应用程序事件。从左侧菜单中选择“应用程序事件”,然后从右侧事件菜单中选择关机。
Private Sub MyApplication_Shutdown(sender As Object,
e As EventArgs) Handles Me.Shutdown
' add your code to Save (above) here
End Sub
同样,您可以让它自动将它们加载到 Startup
中事件。
关于.net - My.Settings 不保存 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25008539/