An object-oriented programming language developed by Microsoft that can be used in .NET.
Use System.Text.Json to deserialize the saved file back into the same AppState type, then rebuild the UI in this order:
- Read the JSON file.
- Deserialize it into
AppState. - Restore the
CheckedListBoxchecked items first. - Let that checked state create any dependent controls.
- Walk through
SingleLabelControlsandMultiLabelControlsand either:- find the existing control and set its properties, or
- create the missing control, add it to the correct
FlowLayoutPanel, and then set its properties.
System.Text.Json ignores JSON properties that are not represented in the class by default, so deserializing into the same model classes is the right approach.
Example load routine in VB:
Imports System.IO
Imports System.Text.Json
Private Sub LoadDataFromInterface(jsonFilePath As String)
Dim jsonString = File.ReadAllText(jsonFilePath)
Dim state = JsonSerializer.Deserialize(Of AppState)(jsonString)
If state Is Nothing Then Exit Sub
' 1. Restore CheckedListBox first
For i As Integer = 0 To CheckedListBox1.Items.Count - 1
CheckedListBox1.SetItemChecked(i, False)
Next
For Each savedItem In state.CheckedItems
For i As Integer = 0 To CheckedListBox1.Items.Count - 1
If CheckedListBox1.Items(i).ToString() = savedItem Then
CheckedListBox1.SetItemChecked(i, True)
Exit For
End If
Next
Next
' 2. Restore single-label controls
For Each data In state.SingleLabelControls
Dim parent = FindFlowLayoutPanelByName(data.ParentName)
If parent Is Nothing Then Continue For
Dim ctrl = parent.Controls.OfType(Of LitratureItem)().
FirstOrDefault(Function(c) c.Name = data.ControlName)
If ctrl Is Nothing Then
ctrl = New LitratureItem()
ctrl.Name = data.ControlName
parent.Controls.Add(ctrl)
End If
ctrl.LblTitle.Text = data.Title
ctrl.LblTitle.ForeColor = data.Forecolor
ctrl.PicImage.Tag = data.ImagePath
ctrl.LblStatus.Text = data.ExtraLabelText
Next
' 3. Restore multi-label controls
For Each data In state.MultiLabelControls
Dim parent = FindFlowLayoutPanelByName(data.ParentName)
If parent Is Nothing Then Continue For
Dim ctrl = parent.Controls.OfType(Of SkillItem)().
FirstOrDefault(Function(c) c.Name = data.ControlName)
If ctrl Is Nothing Then
ctrl = New SkillItem()
ctrl.Name = data.ControlName
parent.Controls.Add(ctrl)
End If
ctrl.LblTitle.Text = data.Title
ctrl.LblTitle.ForeColor = data.Forecolor
ctrl.PicImage.Tag = data.ImagePath
If data.ExtraLabelsText.Count > 0 Then ctrl.LblSkill1.Text = data.ExtraLabelsText(0)
If data.ExtraLabelsText.Count > 1 Then ctrl.LblSkill2.Text = data.ExtraLabelsText(1)
If data.ExtraLabelsText.Count > 2 Then ctrl.LblSkill3.Text = data.ExtraLabelsText(2)
If data.ExtraLabelsText.Count > 3 Then ctrl.LblSkill4.Text = data.ExtraLabelsText(3)
If data.ExtraLabelsText.Count > 4 Then ctrl.LblSkill5.Text = data.ExtraLabelsText(4)
If data.ExtraLabelsText.Count > 5 Then ctrl.LblSkillAll.Text = data.ExtraLabelsText(5)
Next
End Sub
Private Function FindFlowLayoutPanelByName(panelName As String) As FlowLayoutPanel
Return GetAllControls(Me).OfType(Of FlowLayoutPanel)().
FirstOrDefault(Function(f) f.Name = panelName)
End Function
Important points for this design:
- The JSON file should store data, not the controls themselves.
- The control classes (
LitratureItem,SkillItem) should be recreated by code, then populated from the deserialized data. - Restoring the
CheckedListBoxfirst is important because that state may cause the program to create additional controls before the saved control data is applied. - If a control already exists, update it instead of creating a duplicate.
For custom controls in Windows Forms, persistence is typically handled by saving settings data and then loading it back into the control. If a custom control needs to persist its own settings, Windows Forms guidance is to load settings during initialization and save them explicitly.
One thing to verify: Color is being serialized in Forecolor. If that does not round-trip the way expected in the JSON, store a simpler value such as a string or ARGB integer in the data class and convert it when applying the properties.
A practical pattern is:
Public Property ForeColorArgb As Integer
Save with:
.ForeColorArgb = customCtrl.LblTitle.ForeColor.ToArgb()
Load with:
ctrl.LblTitle.ForeColor = Color.FromArgb(data.ForeColorArgb)
That keeps the JSON model simple and avoids issues with complex type serialization.
References: