【问题标题】:Preserve check state of the items in cascading CheckedListBox保留级联 CheckedListBox 中项目的检查状态
【发布时间】:2019-11-30 13:48:01
【问题描述】:

我的 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类:

 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做的

【问题讨论】:

  • Remove() 是否导致问题?
  • @jdweng,我不这么认为。我已经调试了我的程序。 _SelectedDoctorsChecked中的所有项目都是我选择的。它是正确的。我认为_SelectedDoctorsChecked.Contains(DoctorsIDCheckedlistbox.Items[i].ToString()) 行有问题。但我找不到问题。
  • 为了帮助调试,使 DoctorsIDCheckedlistbox.Items[i].ToString() 成为一个变量,如 string doctorName = DoctorsIDCheckedlistbox.Items[i].ToString();然后检查该值是否正确。
  • 它给了我:"EF.DoctorList" for all DoctorsIDCheckedlistbox.Items[i].ToString()
  • 然后您将每个值都添加到“EF.DoctorList”框中。

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


【解决方案1】:

基本原理与我在Updates in the DataSource reset CheckedListBox checkboxes 中解释的相同。

您需要定义一个BindingList&lt;Specialties&gt;作为专科检查列表框的数据源并显示所有专科。

对于医生,您需要一个空的BindingList&lt;CheckedListBoxItem&lt;Doctor&gt;&gt;,并将其设置为医生选中列表框的数据源。那么你需要处理以下事件:

  • ItemChecked 专科选中列表框事件:如果选中该项目,则从您的存储库中查找所有具有选中专科的医生,并将它们作为CheckedListBoxItem&lt;Doctor&gt; 绑定到绑定列表。否则,找到绑定源中所有未勾选专科的医生,将其删除。

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

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

示例

以下是具有 2 个选中的专科和医生列表框并根据所选专科选择医生的场景的完整示例:

模型

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

【讨论】:

  • 非常感谢您的帮助。它工作完美。你介意我问一个关于通过列表搜索的相关问题吗?
  • 不客气。如果新问题可能需要一些代码,最好在单独的帖子中提出新问题;但是,如果您认为这是我可以在 cmets 中回答的问题,请随时在 cmets 中提问。如果您在新帖子中提出问题,请随时让我知道您的新问题,我会看看。
  • 您的好意先生。抱歉耽搁了,我不得不开始工作才能访问相关代码。我在这里发布了一个新问题:stackoverflow.com/questions/59232592/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
相关资源
最近更新 更多