在级联 CheckedListBox 中保留项目的检查状态

Preserve check state of the items in cascading CheckedListBox

我的 C# windows 表单应用程序中有 2 个 Checkedlistbox 控件。第一个 Checkedlistbox 是医生的专业,例如牙医、放射科医生等。如果我选​​中牙医复选框医生的专业 Checkedlistbox 控件,所有牙医都会显示在医生的名字中 Checkedlistbox 控制.
问题是,当我检查牙医 Checkedlistbox 然后医生 Checkedlistbox 的一些牙医时,如果我检查放射科医生 Checkedlistbox,那么医生的名字 Checkedlistbox 将被重置并且我的牙医检查的所有复选框都将被取消选择。
我试过的: 医生姓名Checkedlistbox 数据来源:

DoctorsIDCheckedlistbox.DataSource = _ClinicEntities.Tbl_Doctors
      .Where(w => _SelectedSpecialty.Contains(w.SpecialtyID))
      .Select(s => new DoctorListCheckbox{ Name = s.Name + " " + s.LastName, DoctorID = s.DoctorID })
      .ToList();

DoctorsIDCheckedlistbox.DisplayMember = "Name";
DoctorsIDCheckedlistbox.ValueMember = "DoctorID";

然后我在ItemCheck事件中保存选中的项目:

private void DoctorsID_ItemCheck(object sender, ItemCheckEventArgs e)
{
    int doctorID = Convert.ToInt32(DoctorsIDCheckedlistbox.SelectedValue);
    if (e.NewValue == CheckState.Checked)
    {
        _SelectedDoctorsChecked.Add(doctorID.ToString());
    }
    else
    {
        _SelectedDoctorsChecked.Remove(doctorID.ToString());
    }
}

然后医生专业ItemCheck事件:

private void SpecialtyTypeID_ItemCheck(object sender, ItemCheckEventArgs e)
{
    for (int i = 0; i < DoctorsIDCheckedlistbox.Items.Count; i++)
    {
         if (_SelectedDoctorsChecked.Contains(DoctorsIDCheckedlistbox.Items[i].ToString()))
         {
             try
             {
                 DoctorsIDCheckedlistbox.SetItemChecked(i, true);
             }
             catch (Exception ex)
             {
                 MessageBox.Show(ex.ToString());
             }
        }
    }
}

我希望上面的代码查看选定医生的 _SelectedDoctorsChecked 列表,并在医生的专业复选框状态更改时检查它们。但它不起作用。

示例:
我在医生的专业中勾选A,第1、2、3项将显示在医生的姓名中。我检查 1 和 3。当我检查医生专业中的 B 时,将显示 A 中的项目 1、2 和 3 以及 B 中的 4、5 和 6。我希望检查 1 号和 3 号。但是不会。

编辑:
我的Checkedlistbox控件数据源:

DoctorsIDCheckedlistbox.DataSource = _ClinicEntities.Tbl_Doctors
   .Where(w => _SelectedSpecialty.Contains(w.SpecialtyID))
   .Select(s => new DoctorListCheckbox{ Name = s.Name + " " + s.LastName, DoctorID = s.DoctorID })
   .ToList();

   DoctorsIDCheckedlistbox.DisplayMember = "Name";
   DoctorsIDCheckedlistbox.ValueMember = "DoctorID";

DoctorListCheckbox class:

 public partial class DoctorListCheckbox
 {
    public int DoctorID { get; set; }
    public string Name { get; set; }
    public CheckState CheckState { get; set; }
    public override string ToString()
    {
        return Name;
    }
 }

我是根据Microsoft Example

做的

基本原理和我在中解释的一样。

您需要定义一个BindingList<Specialties>作为专业检查列表框的数据源并显示所有专业。

对于医生,您需要一个空的BindingList<CheckedListBoxItem<Doctor>>并将其设置为医生检查列表框的数据源。那么你需要处理以下事件:

  • ItemChecked 专业检查列表框事件:如果项目被选中,则从您的存储库中找到所有具有检查专业的医生,并将他们作为 CheckedListBoxItem<Doctor> 绑定列表。否则,在绑定源中找到所有未勾选专业的医生,将其移除。

  • ItemChecked医生事件:使用选中列表框项的选中状态同步绑定列表项的选中状态。

  • ListChanged绑定列表事件:同步勾选列表框项勾选状态,使用绑定列表项勾选状态。

例子

这是一个场景的完整示例,该场景具有 2 个选中的专业和医生列表框以及 select 医生基于 selected 专业:

型号

public class Speciality
{
    public int Id { get; set; }
    public string Name { get; set; }
    public override string ToString() { return Name; }
}
public class Doctor
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int SpecialityId { get; set; }
    public override string ToString() { return Name; }
}
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(); }
}

示例数据

public class DB
{
    public IEnumerable<Speciality> Specialities
    {
        get
        {
            return new List<Speciality>()
            {
                new Speciality(){ Id= 1, Name ="S1"},
                new Speciality(){ Id= 2, Name ="S2"},
                new Speciality(){ Id= 3, Name ="S3"},
            };
        }
    }
    public IEnumerable<Doctor> Doctors
    {
        get
        {
            return new List<Doctor>()
            {
                new Doctor(){ Id= 1, Name ="D1", SpecialityId = 1},
                new Doctor(){ Id= 2, Name ="D2", SpecialityId = 2},
                new Doctor(){ Id= 3, Name ="D3", SpecialityId = 2},
                new Doctor(){ Id= 4, Name ="D4", SpecialityId = 3},
                new Doctor(){ Id= 5, Name ="D5", SpecialityId = 3},
                new Doctor(){ Id= 6, Name ="D6", SpecialityId = 3},
            };
        }
    }
}

表单事件处理程序

DB db = new DB();
BindingList<Speciality> specialities;
BindingList<CheckedListBoxItem<Doctor>> doctors;
private void Form10_Load(object sender, System.EventArgs e)
{
    specialities = new BindingList<Speciality>(db.Specialities.ToList());
    specialitiesCheckedListBox.DataSource = specialities;
    doctors = new BindingList<CheckedListBoxItem<Doctor>>();
    doctorsCheckedListBox.DataSource = doctors;
    doctors.ListChanged += doctors_ListChanged;
}
private void doctors_ListChanged(object sender, ListChangedEventArgs e)
{
    for (var i = 0; i < doctorsCheckedListBox.Items.Count; i++) {
        doctorsCheckedListBox.SetItemCheckState(i,
            ((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[i]).CheckState);
    }
}
private void specialitiesCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
    var item = (Speciality)specialitiesCheckedListBox.Items[e.Index];
    if (e.NewValue == CheckState.Checked) {
        db.Doctors.Where(x => x.SpecialityId == item.Id)
            .Select(x => new CheckedListBoxItem<Doctor>(x)).ToList()
            .ForEach(x => doctors.Add(x));
    }
    else {
        doctors.Where(x => x.DataBoundItem.SpecialityId == item.Id)
            .ToList().ForEach(x => doctors.Remove(x));
    }
}
private void doctorsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
    ((CheckedListBoxItem<Doctor>)doctorsCheckedListBox.Items[e.Index])
        .CheckState = e.NewValue;
}