I am trying to maintain a list of checked items in a CheckedListBox
in User Settings and then reload them upon Application load.
In my Settings.se
Since CheckedListBox.CheckedItems
property in not bindable to settings, you should add a string property and store checked items as comma separated string in settings and save settings when closing the form and set checked items of CheckedListBox at form Load.
To save CheckedItems
of a CheckedListBox
:
Settings
file to your project in Properties
folder, or if you have that open it.CheckedItems
Load
event of form, read checked items from settings, and set checked items in CheckedListBox using SetItemChecked
.FormClosing
event, read CheckedItems
of CheckedListBox and save in setting as comma separated string.Code:
private void Form1_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Properties.Settings.Default.CheckedItems))
{
Properties.Settings.Default.CheckedItems.Split(',')
.ToList()
.ForEach(item =>
{
var index = this.checkedListBox1.Items.IndexOf(item);
this.checkedListBox1.SetItemChecked(index, true);
});
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
var indices = this.checkedListBox1.CheckedItems.Cast<string>()
.ToArray();
Properties.Settings.Default.CheckedItems = string.Join(",", indices);
Properties.Settings.Default.Save();
}
How do I know it is not bindable to settings?
As first evidence, for each control in designer mode, in property grid, you can check +(ApplicationSettings
) (PropertyBinding
)[...] to see a list of properties that support property binding.
Furthermore, you should know "Application settings uses the Windows Forms data binding architecture to provide two-way communication of settings updates between the settings object and components."[1]
For example when you bind BackColor
property of your CheckedListBox
to a MyBackColor
property, here is the code that the Designer generates for it:
this.checkedListBox1.DataBindings.Add(
new System.Windows.Forms.Binding("BackColor",
global::StackSamplesCS.Properties.Settings.Default, "MyBackColor", true,
System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
Now let's look at property definition [2]:
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public CheckedListBox.CheckedItemCollection CheckedItems { get; }
The property or indexer
CheckedListBox.CheckedItems
cannot be assigned to because it is read only
Is there a better way?
The short answer for this property is No.
Suppose we have a property MyCheckedItems
:
[UserScopedSetting()]
public CheckedListBox.CheckedItemCollection MyCheckedItems
{
get
{
return ((CheckedListBox.CheckedItemCollection)this["MyCheckedItems"]);
}
set
{
this["MyCheckedItems"] = (CheckedListBox.CheckedItemCollection)value;
}
}
How can we or setting provider instantiate CheckedListBox.CheckedItemCollection
?
The type
CheckedListBox.CheckedItemCollection
has no public constructors defined
So we can not instantiate it. The only constructor that CheckedListBox internally use it is [2]:
internal CheckedItemCollection(CheckedListBox owner)
Furthermore the only way to add an item to this collection is an internal method of CheckedItemCollection
:
internal void SetCheckedState(int index, CheckState value)
So we can't do a better workaround for this property.
More information:
ApplicationSettings
) (PropertyBinding
)[...] to see a list of properties that support property binding. ConvertToString
or ConvertFromString
on the type's associated TypeConverter
. If this does not succeed, it uses XML serialization instead. [1] So For cases that you are not faced with read only properties or constructor-less classes, you can serialize value using a custom TypeConverter
or a custom serializer.