Pergunta

Eu configurei esta propriedade de vazio:

enter image description here

Mas depois de atribuir um novo ListaArray objeto à propriedade, a propriedade sempre permanece vazia em cada execução do aplicativo.

Em um manipulador de MinhaBase.Load evento eu faço uma chamada para este método, apenas para testar este problema:

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

Como você pode ver no código acima, estou atribuindo um novo ArrayList com uma entrada, mas as alterações só entram em vigor durante a execução do aplicativo. Se eu sair do aplicativo, a propriedade ficará vazia novamente.

E também é claro que marquei esta opção:

enter image description here

Mas de qualquer forma isso é desnecessário já que estou salvando a configuração manualmente no código, então...

Por que isso acontece?

Como posso resolver esse problema?

ATUALIZAR:

Eu investiguei e parece que este é um problema conhecido que Arrays, ArrayLists e quaisquer coleções genéricas (do tipo) não podem ser salvas pelo my.settings (mas por outro lado, um StringCollection pode)

Mas na última resposta de esta postagem (a resposta do MemoryStream) explica uma maneira fácil de salvar permanentemente as alterações de um ArrayList em my.settings e depois lê-lo na próxima execução do aplicativo.

A resposta parece muito boa, mas estou um pouco perdido com o código e as etapas para prosseguir, então alguém poderia explicar as etapas explicadas lá, mas em uma linguagem legível para mim, por favor?

Verifiquei que o ArrayList permanece na próxima execução do aplicativo, sim, mas não tenho certeza do que estou fazendo porque se o MemoryStream contém o ArrayList antigo, o que estou fazendo agora é atribuir o My.Settings. Configuração MRU como um Arraylist que contém mais Arraylists em vez disso, o ArrayList original que continha um String() ?, e de qualquer forma, como carregar as entradas do array depois de salvar a configuração desta forma?.

Isso é o que tentei com essa resposta:

' 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)
Foi útil?

Solução

Se você tiver os dados em um arrayList (ou Lista ou Coleção) e estiver procurando uma solução alternativa no BinaryFormatter, não há um bom motivo para usar também My.Settings.Você pode fazer o que faz através do BinaryFormatter, que é apenas salvar o arquivo e escolher um nome.

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)

Salvar configurações:

Dim bf As New BinaryFormatter
Using fs As New FileStream(myFile, FileMode.OpenOrCreate)
    bf.Serialize(fs, MRUArrayList )
End Using

Carregar configurações:

' 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

Uma vez que você tenha que recorrer ao BF para a solução alternativa, substituir o Memory Stream por um File Stream elimina totalmente a necessidade de My.Settings, permite armazenar o arquivo onde quiser e ele não será alterado por versão, o usuário altera o nome do EXE ou qualquer outra coisa, a menos que você altere a fórmula do nome do arquivo acima.

Para um aplicativo com mais do que apenas o MRU ArrayList, você pode usar uma classe em seu lugar para armazenar todas as configurações no local desejado, da mesma forma que as configurações fazem.Você só precisa marcar a classe como <Serializable>.Resta uma linha de código para salvar a classe inteira, uma linha para reconstituí-la.Existem algumas limitações, mas não são difíceis de superar.

Private myNewSettings As New myNewSettingsClass
...

bf.Serialize(fs, myNewSettings)

myNewSettings = CType(bf.Deserialize(fs), myNewSettingsClass )

Em outras situações, você pode usar o serializador XML ou ProtoBuf-NET conforme necessário para a situação.

Você também pode salvar suas novas configurações automaticamente quando o programa for encerrado:Vá para Propriedades do projeto --> Aplicativo --> Clique em Exibir eventos do aplicativo.Selecione "Eventos de aplicativos" no menu esquerdo e Desligar no menu de eventos à direita.

Private Sub MyApplication_Shutdown(sender As Object, 
          e As EventArgs) Handles Me.Shutdown

   ' add your code to Save (above) here
End Sub

Da mesma forma, você pode fazer com que ele os carregue automaticamente no Startup evento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top