My.Settings は ArrayList を保存しません
-
20-12-2019 - |
質問
この空のプロパティを設定しました。
しかし、新しいものを割り当てた後、 配列リスト オブジェクトをプロパティに追加しても、アプリケーションの実行のたびにプロパティは常に空のままです。
のハンドラーで 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
上記のコードでわかるように、1 つのエントリを持つ新しい ArrayList を割り当てていますが、変更はそのアプリケーションの実行中にのみ有効になり、アプリを終了するとプロパティは再び空になります。
そしてもちろん、このオプションもチェックしました:
しかし、とにかく、設定をコードに手動で保存しているので、それは不要です。
なぜこのようなことが起こるのでしょうか?
この問題はどうすれば解決できますか?
アップデート:
調査したところ、これは、配列、ArrayList、および汎用コレクション(Of Type)が my.settings で保存できないという既知の問題のようです(ただし、一方で StringCollection は保存できます)。
しかし、最後の答えでは、 この郵便受け (MemoryStream の回答) では、ArrayList の変更を my.settings に永続的に保存し、次回のアプリケーション実行時にそれを読み取る簡単な方法について説明しています。
答えはとても良さそうですが、コードと次に進む手順が少し分からないので、誰かがそこで説明されている手順を人間が読める言語で説明してもらえますか?
ArrayList が次のアプリケーション実行時にも残ることを確認しました。はい、しかし、MemoryStream に古い ArrayList が含まれている場合、今私が行っていることは My.Settings の割り当てなので、何をしているのかわかりません。より多くの内容を含むアレイリストとしての MRU 設定 Arraylists
代わりに、元の ArrayList には String()
? そしてとにかく、この方法で設定を保存した後に配列エントリをロードするにはどうすればよいですか?
これは私がその答えから試したことです:
' 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 に頼る必要がある場合は、Memory Stream を File Stream に置き換えることで、My.Settings の必要性が完全になくなり、ファイルをどこにでも保存できるようになり、バージョンによって変更されず、ユーザーが EXE 名を変更できるようになります。上記のファイル名の式を変更しない限り、他のものでも構いません。
MRU ArrayList 以外のアプリの場合は、設定と同じようにクラスを代わりに使用して、すべての設定を必要な場所に保存できます。クラスにタグを付けるだけです <Serializable>
. 。クラス全体を保存するには 1 行のコードが残り、再構成するには 1 行のコードが残ります。いくつかの制限がありますが、克服するのは難しくありません。
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
イベント。