سؤال

لقد قمت بتعيين خاصية الفراغ هذه:

enter image description here

ولكن بعد تعيين جديد 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 جديدة بإدخال واحد، لكن التغييرات تصبح سارية المفعول فقط أثناء تنفيذ تطبيق التطبيق هذا، وإذا خرجت من التطبيق، فستصبح الخاصية فارغة مرة أخرى.

وبالطبع قمت أيضًا بتحديد هذا الخيار:

enter image description here

لكن هذا غير ضروري على أي حال لأنني أحفظ الإعداد يدويًا في الكود، لذا...

لماذا يحدث هذا؟.

كيف يمكنني حل هذه المشكلة؟.

تحديث:

لقد قمت بالتحقيق ويبدو أن هذه مشكلة معروفة وهي أن المصفوفات وقوائم المصفوفات وأي مجموعات عامة (من النوع) لا يمكن حفظها بواسطة 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 (أو قائمة أو مجموعة)، وكنت تبحث في 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