Вопрос

Я установил это свойство пустоты:

enter image description here

Но после назначения нового ArrayList объект для свойства, свойство всегда остается пустым при каждом выполнении приложения.

В обработчике MyBase.Load event я вызываю этот метод просто для проверки этой проблемы:

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 с одной записью, но изменения вступают в силу только во время выполнения этого приложения. Если я выхожу из приложения, свойство снова становится пустым.

И, конечно же, я проверил этот вариант:

enter image description here

Но в любом случае в этом нет необходимости, поскольку я сохраняю настройки вручную в коде, так что...

Почему это происходит?

Как я могу решить эту проблему?

ОБНОВЛЯТЬ:

Я исследовал и кажется, что это известная проблема: массивы, ArrayLists и любые общие коллекции (типа) не могут быть сохранены с помощью 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 в качестве обходного пути, замена потока памяти на файловый поток полностью избавит вас от необходимости в 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 событие.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top