将 CheckedListBox 项目保存到设置

Save CheckedListBox Items to Settings

我正在尝试在用户设置的 CheckedListBox 中维护一个检查项目列表,然后在应用程序加载时重新加载它们。

在我的 Settings.settings 文件中,我添加了以下内容:

<Setting Name="obj" Type="System.Windows.Forms.CheckedListBox.ObjectCollection" Scope="User">
    <Value Profile="(Default)" />
</Setting>

而且,在 chkList_ItemCheck,我正在做以下事情:

Properties.Settings.Default.obj = chkList.Items;
Properties.Settings.Default.Save()

但由于某些原因,当我退出应用程序时,重新打开并查看 Properties.Settings.Default.obj 的值,它是 null

我在做什么wrong/missing?

由于 CheckedListBox.CheckedItems 属性 无法绑定到设置,您应该添加一个字符串 属性 并将选中的项目存储为设置中的逗号分隔字符串并在关闭表单时保存设置和在表单加载时设置 CheckedListBox 的选中项。

要保存 CheckedItemsCheckedListBox:

  1. Settings 文件添加到您的 Properties 文件夹中的项目,或者如果您有该文件,请打开它。
  2. 添加名为 CheckedItems
  3. 的字符串设置 属性
  4. 在表单的Load事件中,从设置中读取选中项,并使用SetItemChecked在CheckedListBox中设置选中项。
  5. FormClosing事件中,读取CheckedListBox的CheckedItems并在设置中保存为逗号分隔字符串。

代码:

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();
}

我怎么知道它不能绑定到设置?

作为第一个证据,对于设计器模式下的每个控件,在 属性 网格中,您可以检查 +(ApplicationSettings) (PropertyBinding)[...] 以查看支持 属性 绑定的属性列表。

此外,您应该知道“应用程序设置使用 Windows 表单数据绑定体系结构来提供设置对象和组件之间设置更新的双向通信。 "[1]

例如,当您将 CheckedListBoxBackColor 属性 绑定到 MyBackColor 属性 时,这是设计器为其生成的代码:

this.checkedListBox1.DataBindings.Add(
    new System.Windows.Forms.Binding("BackColor", 
    global::StackSamplesCS.Properties.Settings.Default, "MyBackColor", true,
    System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));

现在让我们看看属性定义[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

有没有更好的方法?

这个 属性 的简短答案是否定的。

假设我们有一个 属性 MyCheckedItems:

[UserScopedSetting()]
public CheckedListBox.CheckedItemCollection MyCheckedItems
{
    get
    {
        return ((CheckedListBox.CheckedItemCollection)this["MyCheckedItems"]);
    }
    set
    {
        this["MyCheckedItems"] = (CheckedListBox.CheckedItemCollection)value;
    }
}

我们或设置提供者如何实例化CheckedListBox.CheckedItemCollection

The type CheckedListBox.CheckedItemCollection has no public constructors defined

所以我们不能实例化它。 CheckedListBox 内部使用的唯一构造函数是 [2]:

internal CheckedItemCollection(CheckedListBox owner)

此外,将项目添加到此集合的唯一方法是 CheckedItemCollection:

的内部方法
internal void SetCheckedState(int index, CheckState value)

所以我们无法为此做更好的解决方法 属性。

更多信息:

  • 对于设计器模式下的每个控件,在 属性 网格中,您可以检查 +(ApplicationSettings) (PropertyBinding)[...] 以查看属性列表支持 属性 绑定。
  • 设置序列化以这种方式工作,它首先尝试在类型的关联 TypeConverter 上调用 ConvertToStringConvertFromString。如果不成功,它会改用 XML 序列化。 [1] 因此,如果您没有遇到只读属性或无构造函数 类,您可以使用自定义 TypeConverter 或自定义序列化程序序列化值。