为了账号安全,请及时绑定邮箱和手机立即绑定

数据源中的更新重置 CheckedListBox 复选框

数据源中的更新重置 CheckedListBox 复选框

C#
蝴蝶刀刀 2023-09-16 17:26:45
我有一个 CheckedListBox,绑定到 BindingList:private BindingList<string> list = new BindingList<string>();public MyForm(){    InitializeComponent();    list.Add("A");    list.Add("B");    list.Add("C");    list.Add("D");    checkedListBox.DataSource = collection;}单击某个按钮时,列表会更新:private void Button_Click(object sender, EventArgs e){    list.Insert(0, "Hello!");}它工作正常,CheckedListBox 已更新。但是,当选中某些项目时,单击该按钮不仅会更新列表,还会将所有项目重置为取消选中。我该如何解决这个问题?
查看完整描述

2 回答

?
慕的地6264312

TA贡献1817条经验 获得超6个赞

您需要自己跟踪检查状态。

作为一个选项,您可以为包含文本和检查状态的项目创建模型类。然后在ItemCheck控制事件中,设置项目模型的检查状态值。另外,ListChenged如果您BindingList<T>刷新检查项目状态。

例子

创建CheckedListBoxItem类:

public class CheckedListBoxItem

{

    public CheckedListBoxItem(string text)

    {

        Text = text;

    }

    public string Text { get; set; }

    public CheckState CheckState { get; set; }

    public override string ToString()

    {

        return Text;

    }

}

设置CheckedListBox如下:


private BindingList<CheckedListBoxItem> list = new BindingList<CheckedListBoxItem>();

private void Form1_Load(object sender, EventArgs e)

{

    list.Add(new CheckedListBoxItem("A"));

    list.Add(new CheckedListBoxItem("B"));

    list.Add(new CheckedListBoxItem("C"));

    list.Add(new CheckedListBoxItem("D"));

    checkedListBox1.DataSource = list;

    checkedListBox1.ItemCheck += CheckedListBox1_ItemCheck;

    list.ListChanged += List_ListChanged;

}

private void CheckedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)

{

    ((CheckedListBoxItem)checkedListBox1.Items[e.Index]).CheckState = e.NewValue;

}

private void List_ListChanged(object sender, ListChangedEventArgs e)

{

    for (var i = 0; i < checkedListBox1.Items.Count; i++)

    {

        checkedListBox1.SetItemCheckState(i,

            ((CheckedListBoxItem)checkedListBox1.Items[i]).CheckState);

    }

}


查看完整回答
反对 回复 2023-09-16
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

另一种方法。它不需要自定义类的支持(尽量不这样做)。

由于在这种情况下,基础项目列表是非托管的(在其他地方托管),因此必须手动处理项目的检查状态。
有趣的是,查看在列表中添加或删除项目时引发的事件的顺序是什么BindingList(例如,在列表更新之前没有通知列表更改的事件,ListChangedEventArgs.OldIndex从未设置,因此始终-1等)。 )。

由于 CheckedListBox 的来源很简单List<string>,因此当列表更新时,ItemCheckState会丢失。因此,需要存储这些状态并在需要时重新应用,调用SetItemCheckedState方法。

由于必须调整项目的状态以匹配新的列表组成(在删除或插入项目之后)并且此过程是同步的,因此事件ItemCheck(用于更新所有项目CheckState)会异常引发并需要延迟执行。这就是为什么BeginInvoke()这里使用的原因。

总而言之,在内部存储这些状态的专用类对象是正确的选择。在这里,绑定由于缺乏基类的支持而受到影响。并不是说它在任何地方都另有说明:CheckedListBox.DataSource例如,甚至无法浏览。

private BindingList<string> clbItemsList = new BindingList<string>();

public MyForm()

{

    InitializeComponent();

    clbItemsList.Add("A");

    // (...)

    checkedListBox1.DataSource = clbItemsList;

    clbItemsList.ListChanged += this.clbListChanged;

    checkedListBox1.ItemCheck += (s, e) => { BeginInvoke(new Action(()=> CheckedStateCurrent())); };

}


private void clbListChanged(object sender, ListChangedEventArgs e)

{

    foreach (var item in clbCheckedItems.ToArray()) {

        if (e.ListChangedType == ListChangedType.ItemAdded) {

            checkedListBox1.SetItemCheckState(item.Index >= e.NewIndex ? item.Index + 1 : item.Index, item.State);

        }

        if (e.ListChangedType == ListChangedType.ItemDeleted) {

            if (item.Index == e.NewIndex) { 

                clbCheckedItems.Remove(item);

                continue;

            }

            checkedListBox1.SetItemCheckState(item.Index > e.NewIndex ? item.Index - 1 : item.Index, item.State);

        }

    }

}


private List<(CheckState State, int Index)> clbCheckedItems = new List<(CheckState State, int Index)>();

private void CheckedStateCurrent()

{

    clbCheckedItems = checkedListBox1.CheckedIndices.OfType<int>()

        .Select(item => (checkedListBox1.GetItemCheckState(item), item)).ToList();

}


查看完整回答
反对 回复 2023-09-16
  • 2 回答
  • 0 关注
  • 123 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信