【问题标题】:Filter cascading CheckedListBox and preserve check state of the items过滤级联 CheckedListBox 并保留项目的检查状态
【发布时间】:2019-12-08 05:05:57
【问题描述】:

我前几天问过This Question,答案完美解决了我的问题。我对自己的帖子还有另一个相关问题。

当我通过检查第一个(专业)Checkedlistbox 项目更改数据源时,将保存第二个(医生)Checkedlistbox 项目的CheckState。这是我的代码:

CheckedListBoxItem类:

/// <summary>
/// A class to svae status of checkboxes when datasource changes.
/// </summary>
/// <typeparam name="T"></typeparam>
public class CheckedListBoxItem<T>
{
    public CheckedListBoxItem(T item)
    {
        DataBoundItem = item;
    }
    public T DataBoundItem { get; set; }
    public CheckState CheckState { get; set; }
    public override string ToString() { return DataBoundItem.ToString(); }
}

SpecialityCheckListDoctorCheckList 与第一个和第二个 Checkedlistbox 控件相关:

public class SpecialityCheckList
{
    public int SpecialtyID { get; set; }
    public string Title { get; set; }
    public override string ToString() { return Title; }
}

public class DoctorCheckList
{
    public int DoctorID { get; set; }
    public string Name { get; set; }
    public int? SpecialityId { get; set; }
    public override string ToString() { return Name; }
}

表格代码:

BindingList<CheckedListBoxItem<DoctorCheckList>> doctors = new BindingList<CheckedListBoxItem<DoctorCheckList>>();

private void ReportVisitSocialInsurance_Load(object sender, EventArgs e)
{
     SpecialtyTypeCheckbox.DataSource = new BindingList<SpecialityCheckList>(_Specialty.SelectTbl_SpecialityCheckListBox());

     DoctorsIDCheckedlistbox.DataSource = doctors;
     doctors.ListChanged += Doctors_ListChanged;
}

private void Doctors_ListChanged(object sender, ListChangedEventArgs e)
{
     for (var i = 0; i < DoctorsIDCheckedlistbox.Items.Count; i++)
     {
         DoctorsIDCheckedlistbox.SetItemCheckState(i, ((CheckedListBoxItem<DoctorCheckList>)DoctorsIDCheckedlistbox.Items[i]).CheckState);
     }
}

private void SpecialtyTypeID_ItemCheck(object sender, ItemCheckEventArgs e)
{
     var item = (SpecialityCheckList)SpecialtyTypeCheckbox.Items[e.Index];
     if (e.NewValue == CheckState.Checked)
     {
          _Doctors.SelectTbl_DoctorsCheckListBox(item.SpecialtyID)
                    .Select(s => new CheckedListBoxItem<DoctorCheckList>(s)).ToList()
                    .ForEach(f => doctors.Add(f));
     } else {
          doctors
                    .Where(w => w.DataBoundItem.SpecialityId == item.SpecialtyID)
                    .ToList()
                    .ForEach(f => doctors.Remove(f));
     }
}

private void DoctorsID_ItemCheck(object sender, ItemCheckEventArgs e)
{
      ((CheckedListBoxItem<DoctorCheckList>)DoctorsIDCheckedlistbox.Items[e.Index]).CheckState = e.NewValue;
}

如果我搜索医生的Checkedlistbox 项目并检查一个项目,当我清除搜索文本框以查看所有医生的姓名时,检查的项目与我在搜索时检查的项目不同。这是因为它使用我认为的索引。这是我搜索时的代码:

private void DoctorsNameTextbox_TextChanged(object sender, EventArgs e)
{
     BindingList<CheckedListBoxItem<DoctorCheckList>> doctorsSerach =
                ObjectCloning.CloneJson<BindingList<CheckedListBoxItem<DoctorCheckList>>>(doctors);

     doctorsSerach
                .Where(w => !w.DataBoundItem.Name.Contains(DoctorsNameTextbox.Text))
                .ToList()
                .ForEach(f => doctorsSerach.Remove(f));

     DoctorsIDCheckedlistbox.DataSource = doctorsSerach;
}

问题是,例如,如果我搜索姓名 Ali,它会显示 3 个项目。当我检查项目编号 2 并清除搜索文本框时,索引 1(从零开始)处的项目已被检查。

【问题讨论】:

    标签: c# .net winforms data-binding checkedlistbox


    【解决方案1】:

    在处理searchTextBoxTexctChanged事件时,可以检查文本是否为空,将数据源设置为医生列表,否则将数据源设置为过滤后的医生列表。在这两种情况下,设置数据源后,将复选标记与数据源同步:

    private void searchTextBox_TextChanged(object sender, EventArgs e)
    {
        if(string.IsNullOrEmpty(searchTextBox.Text))
        {
            doctorsCheckedListBox.DataSource = doctors;
        }
        else
        {
            var filteredDoctors = 
                new BindingList<CheckedListBoxItem<Doctor>>
                (doctors.Where(x => x.DataBoundItem.Name.StartsWith(searchTextBox.Text))
                .ToList());
            doctorsCheckedListBox.DataSource = filteredDoctors;
        }
        for (var i = 0; i < doctorsCheckedListBox.Items.Count; i++)
        {
            doctorsCheckedListBox.SetItemCheckState(i,
                ((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[i]).CheckState);
        }
    }
    

    【讨论】:

    • 非常感谢,我被这个问题困扰了很长时间。它现在运行良好。真的谢谢。
    • 一般来说,只要有可能,我宁愿使用DataGridView 而不是CheckedListBox
    • 我会记住的,先生。感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多